#!/usr/bin/python
# coding: iso-8859-15

'''haclient.py, the GUI manamgement tool for Linux-HA'''
import sys, os, string, socket, syslog, webbrowser, pickle, xml, gc, time, binascii, thread, tarfile, tempfile
from stat import *
from xml.dom.minidom import parseString
from xml.dom.minidom import getDOMImplementation
import re
import pdb
import locale, gettext
app_name = "haclient"

sys.path.append("@HA_DATADIR@/heartbeat-gui")
sys.path.append("@LIBDIR@/heartbeat-gui")

from nkha_constants import *
__authors__ = AUTHORS
__license__ = GPLV2PLUS
from license_register import HALicenseManager, HALic_ctrl_IS_flag
from basefunc import confirmbox, msgbox

from IPy import IP
from pymgmt import *

import pygtk
pygtk.require('2.0')
import gtk, gobject, gtk.glade
import datetime

from alarm import alarmview
from drbd import drbdview
from importview import importview
from nethb import addnethbview
from mirror import mirror_and_recoveryview
from qdisk import qudiskview
from serial import addserialhbview
#from switch import switchview
from upgrade import upgradeview
from diskhb import adddiskhbview
from gfs import gfsview
from script import script_generatorview
from sfex import sfexview
from sync import syncview

support_pyxml = False
try:
       from xml.parsers.xmlproc.xmldtd import load_dtd_string
       support_pyxml = True
except ImportError :
       pass

support_lxml = False
try :
	from lxml import etree
	support_lxml = True
except ImportError :
	pass

support_gv = False
try :
	import gv
	support_gv = True
except ImportError :
	pass

validate_type = "dtd"
mode_level = 0
name_cap = lambda name: name.replace("-"," ").replace("_"," ").title().replace("Crmd","CRMD").\
				replace("Crm","CRM").replace("Pe ", "PE ").replace("Dc ","DC ").\
				replace("Cib", "CIB").replace("Ccm", "CCM").replace("Ha", "HA").\
				replace("Id", "ID").replace("Dtd", "DTD").replace("Uuid", "UUID").\
				replace("HAve", "Have").replace("Op ", "Operation ").replace("Rsc", "Resource").\
				replace("Lrm", "LRM").replace("Acl", "ACL")

window = None
manager = None
debug_level = 0
top_window = None
last_rsc_view_page_num = 0	
last_compound_view_page_num = 0
last_cluster_view_page_num = 0

#neoshineha ming.liu
UI_FILE = "@HA_DATADIR@/heartbeat-gui/haclient.glade"
selected_row_num = 0

treeview_status = dict()

def record_treeview_status(treeview, data):
        global treeview_status
        model = treeview.get_model()
        rootiter = model.get_iter_first()
        iter = model.iter_children(rootiter)
        while iter:
                path = model.get_path(iter)
                treeview_status[path] = treeview.row_expanded(path)
                iter = model.iter_next(iter)

def chk_expanded(tree, name):
        model = tree.widget.get_model()
        root = model.get_iter_first()
	if model.get_value(root, 0) == name:
        	return tree.widget.row_expanded(model.get_path(root))
	return chk_child_expanded(tree, model, root, name)

def chk_child_expanded(tree, model, root, name):
        iter = model.iter_children(root)
        while iter:
                if model.get_value(iter, 0) == name:
                        return tree.widget.row_expanded(model.get_path(iter))
		ret = chk_child_expanded(tree, model, iter, name)
		if ret != None:
			return ret
                iter = model.iter_next(iter)

def always_expand(treeview, iter, path, data):
        if len(path) == 1:
                treeview.expand_row(path, False)
        record_treeview_status(treeview, data)
	window.select_view(None, None, None)

def record_expand(treeview, iter, path, data):
        record_treeview_status(treeview, data)
	window.select_view(None, None, None)

def fake_collapsed(treemodel, iter, path, data):
	window.select_view(None, None, None)
        pass

class mainnodeview:
        iconfile = '@HA_DATADIR@/heartbeat-gui/ha.png'
	def update(self):
		self.widget_is_callback.set_active(self.is_callback_new)
		if self.xml_monitor != None and manager.get_rsc_type(self.rsc) == "primitive":
			self.widget_is_monitor.set_sensitive(True)
			self.widget_is_monitor.set_active(self.is_monitor_new)
		else:
			self.widget_is_monitor.set_active(False)

		combo_node_list = gtk.ListStore(gobject.TYPE_STRING)
		for node in self.no_run_node_list_new:  #self.nodes :
			combo_node_list.append([node])
                self.widget_back_node.set_model(combo_node_list)

		combo_rsc_list = gtk.ListStore(gobject.TYPE_STRING)
		for rsc in self.other_rsc_list :
			combo_rsc_list.append([rsc])
		self.widget_colocation_rsc.set_model(combo_rsc_list)

		backup_node_view = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
		back_nodes = self.back_node_list.keys()
		if back_nodes != None :
			back_nodes.sort()
		for key in back_nodes:
			level = self.turn_score_to_level(self.back_node_list[key])
			backup_node_view.append([key, level])
		self.widget_back_node_view.set_model(backup_node_view)

		level_list = gtk.ListStore(gobject.TYPE_STRING)
		level_list.append([_("Master Node")])
		for level in range(len(self.level_score)):
			level_list.append([_("Slave %d")%(level+1)])
		#level_list.append([_("No Run Node")])
		self.widget_level.set_model(level_list)

		self.widget_norun_node.set_text(str(self.no_run_node_list_new))

		left_rsc_view = gtk.ListStore(gobject.TYPE_STRING)
		for rsc in self.same_node_rsc_list:
			left_rsc_view.append([rsc])
		self.widget_left_view.set_model(left_rsc_view)

                if self.first_update:
                        self.widget_back_node.set_text_column(0)
                        self.widget_colocation_rsc.set_text_column(0)
                        self.widget_level.set_text_column(0)
                        self.first_update = False

		return

	def turn_score_to_level(self, score):
		if score in ["20000"]: #["INFINITY", "+INFINITY", "infinity", "+infinity"]:
			return _("Master Node")

		if score in ["-INFINITY", "-infinity"]:
			return _("No Run Node")

		if score not in self.level_score:
			return score
		level = 1
		for s in self.level_score:
			if s == score:
				return _("Slave %d")%(level)
			level = level+1

		return score

	def turn_level_to_score(self, level):
		if level == _("Master Node"):
			return "20000"#"INFINITY"

		if level == _("No Run Node"):
			return "-INFINITY"

                if _("Slave ") not in level :
			return level
		else:
			index = int(level[len(str(_("Slave "))):])
			return self.level_score[index-1]

	def add_score(self, score1, score2):
		if score1 in ["-INFINITY", "-infinity"] or score2 in ["-INFINITY", "-infinity"] :
			return str("-INFINITY")
                if score1 in ["INFINITY","+INFINITY", "infinity", "+infinity"] or score2 in ["INFINITY", "+INFINITY", "infinity", "+infinity"] :
                        return str("INFINITY")
		return str(int(score1)+int(score2))

	def level_init(self):
		self.level_score_new = []  #list(self.level_score)
		max = len(self.nodes)-1
		for i in range(max):
			self.level_score_new.append(str(16000-1000*i))

		self.save_level()
		return

	def data_init(self, rsc):
                self.level_score = []
                self.xml_level = manager.xml_nodes["cib"].getElementsByTagName("heartbeatlevel")
                if self.xml_level != [] :
                        for level in self.xml_level[0].getElementsByTagName('nvpair'):
                                if level.nodeType != xml.dom.Node.ELEMENT_NODE :
                                        continue
                                self.level_score.append(level.getAttribute('value'))

		if len(self.level_score)<len(self.nodes)-1:
			self.level_init()

		self.level_score.sort()
		self.level_score.reverse()

		self.is_callback = True
		self.xml_callback = None
                for meta_attributes_node in self.xml_node.getElementsByTagName("meta_attributes") :
                        for nv_xml_node in meta_attributes_node.getElementsByTagName("nvpair") :
                                if nv_xml_node.getAttribute("name") == "resource-stickiness":
					self.xml_callback = nv_xml_node
                                	if nv_xml_node.getAttribute("value") in ["INFINITY", "+INFINITY", "infinity", "+infinity"]:
						self.is_callback = False
                        		break
		self.is_callback_new = self.is_callback

                self.is_monitor = False
		self.xml_monitor = None
                for meta_attributes_node in self.xml_node.getElementsByTagName("operations") :
                        for nv_xml_node in meta_attributes_node.getElementsByTagName("op") :
                                if nv_xml_node.getAttribute("name") == "monitor":
					self.is_monitor = True
					self.xml_monitor = nv_xml_node
                                        if nv_xml_node.getAttribute("enabled") == "false" :
                                                self.is_monitor = False
                                        break
		self.is_monitor_new = self.is_monitor

		location = {}
		colocation = {}
		self.location_ids = {}
		self.colocation_ids = {}
		constraints = manager.do_cmd("get_rsc_constraints\n%s"%(rsc))
		while constraints == None:
                        constraints = manager.do_cmd("get_rsc_constraints\n%s"%(rsc))

		for cons in constraints :
			#m = re.match('^.*\'(.*)\':(.*)=(.*)$', cons)
			m = re.match('^\s\s:\sNode\s(.*)\s*\(score=(.*)\,\sid=(.*)\)', cons)
                        if m is not None : #location
				node = m.groups()[0].strip()
				score = m.groups()[1].strip()
				if node in location.keys():
					location[node] = self.add_score(score, location[node])
				else:
					location[node] = str(score)
				self.location_ids[str(m.groups()[2].strip())] = str(node)
			else : #colocation
				m = re.match('^(.*)\s*\(score=(.*)\,\sid=(.*)\)', cons)
				if m is None:
					continue
				rsc = m.groups()[0].strip()
				score = m.groups()[1].strip()
				if rsc in colocation.keys():
					colocation[rsc] = self.add_score(score, colocation[rsc])
				else:
					colocation[rsc] = str(score)
				self.colocation_ids[str(m.groups()[2].strip())] = str(rsc)

		self.back_node_list = {}
		self.no_run_node_list = []
		self.main_node = ""
		self.same_node_rsc_list = []
		self.other_rsc_list = []
		self.location = {}
		self.colocation = {}

		#colocation
		for rsc in self.resources:
			self.other_rsc_list.append(rsc)

		for key in colocation.keys() :
                        self.colocation[key] = colocation[key]
                	if colocation[key] in ["INFINITY", "+INFINITY", "infinity", "+infinity"]:
                        	self.same_node_rsc_list.append(key)
				if key in self.other_rsc_list:
					self.other_rsc_list.remove(key)

		#location
		for node in self.nodes:
			self.no_run_node_list.append(node)

		for key in location.keys() :
			self.no_run_node_list.remove(key)
			self.back_node_list[key] = location[key]
			self.location[key] = location[key]

		if "false" not in manager.do_cmd("system\n%s"%("crm_attribute -G -n symmetric-cluster -Q")) :
			self.widget_other_node_label.set_text(_("This is Symmetric Cluster. The resources can also run on other nodes are not configured:"))
		else:
			self.widget_other_node_label.set_text(_("This is Non-symmetric Cluster. The resources can not run on other nodes are not configured:"))

		self.main_node_new = self.main_node
		self.no_run_node_list_new = list(self.no_run_node_list)

	def on_back_node_selected(self, wdiget):
		selection = self.widget_back_node_view.get_selection()
                model, pathlist = selection.get_selected_rows()
                iterlist = [] 
                for path in pathlist:
                        if not model[path][0]:
                                continue
                        iter = model.get_iter(path)
                        node = model.get_value(iter, 0)
                        level = model.get_value(iter, 1)
                        self.widget_back_node.child.set_text(node)
                        self.widget_level.child.set_text(level)

		return

	def on_del_back_node(self, widget):
                selection = self.widget_back_node_view.get_selection()
                model, pathlist = selection.get_selected_rows()
                iterlist = []
		for path in pathlist:
			if not model[path][0]:
				continue
			iter = model.get_iter(path)
			iterlist.append(iter)
			node = model.get_value(iter, 0)
			self.no_run_node_list_new.append(node)
			self.back_node_list.pop(node)

		self.update()
		self.widget_back_node.child.set_text("")
		self.widget_level.child.set_text("")
		self.changed = True
		return

	def on_add_back_node(self, widget):
		node = self.widget_back_node.child.get_text()
		level = self.widget_level.child.get_text()
		if node == "" or level == "" :
			self.widget_back_node.child.set_text("")
			self.widget_level.child.set_text("")
			return

		if node not in self.back_node_list.keys():
			self.no_run_node_list_new.remove(node)

		self.back_node_list[node] = self.turn_level_to_score(level)
		self.update()
		self.widget_back_node.child.set_text("")
		self.widget_level.child.set_text("")
		self.changed = True
		return

	def on_del_view(self, widget):
		selection = self.widget_left_view.get_selection()

                model, pathlist = selection.get_selected_rows()
                for path in pathlist:
                        if model[path][0] :
                                iter = model.get_iter(path)
				self.widget_colocation_rsc.append_text(model.get_value(iter,0))
	                        model.remove(iter)
		selection.unselect_all()
		self.changed = True
		return

	def on_add_colocation(self, widget):
                rsc = self.widget_colocation_rsc.child.get_text()
                if rsc == "" :
                        return

	        self.widget_left_view.get_model().append([rsc])

                model = self.widget_colocation_rsc.get_model()
                iter = self.widget_colocation_rsc.get_active_iter()
                if iter != None:
                        model.remove(iter)
                self.widget_colocation_rsc.child.set_text("")

		self.changed = True
		return

	def save(self):
		if not self.changed:
			return 0

		if self.widget_is_callback.get_property("sensitive"):
			if self.widget_is_callback.get_active() != self.is_callback:
				#change resource_stickiness
				if self.widget_is_callback.get_active():
					score = "0"
				else:
					score = 'INFINITY'
				if self.xml_callback != None:
					self.xml_callback.setAttribute("value", score)
				else:
					impl = getDOMImplementation()
					newdoc = impl.createDocument(None, "nvpair", None)
		                        nv = newdoc.documentElement
					nv.setAttribute('id', str("%s-meta_attributes-resource-stickiness"%(self.rsc)))
					nv.setAttribute('name', str("resource-stickiness"))
					nv.setAttribute('value',str(score))
		                        self.xml_node.getElementsByTagName("meta_attributes")[0].appendChild(nv)

		if self.widget_is_monitor.get_property("sensitive"):
			if self.widget_is_monitor.get_active() != self.is_monitor:
				#change monitor
				if self.widget_is_monitor.get_active():
					self.xml_monitor.setAttribute("enabled", str("true"))
				else:
					self.xml_monitor.setAttribute("enabled", str("false"))

		xml_str = self.xml_node.toxml().replace("\n", "")
                manager.cib_do_cmd("cib_replace\n%s\n%s"%(str(self.xml_node.tagName), str(xml_str)))

                if manager.failed_reason != "" :
                        msgbox(top_window, manager.failed_reason)

		self.location_new = {}

		selection = self.widget_back_node_view.get_selection()
                selection.select_all()
                model, pathlist = selection.get_selected_rows()
                for path in pathlist:
                        if model[path][0] :
                                iter = model.get_iter(path)
				self.location_new[model.get_value(iter, 0)] = self.turn_level_to_score(model.get_value(iter, 1))

		self.colocation_new = {}

		selection = self.widget_left_view.get_selection()
                selection.select_all()
                model, pathlist = selection.get_selected_rows()
                for path in pathlist:
                        if model[path][0] :
                                iter = model.get_iter(path)
                                self.colocation_new[model.get_value(iter, 0)] = "INFINITY"


		xml_constraints = manager.xml_nodes["cib"].getElementsByTagName("constraints")[0]
		#get old locations
                rsc_locations = {}
		rsc_location_rule = []
                for rsc_location in manager.xml_nodes["cib"].getElementsByTagName("rsc_location") :
                        id = str(rsc_location.getAttribute("id"))
                        if id in self.location_ids.keys():
				if self.location_ids[id] not in rsc_locations.keys():
					rsc_locations[self.location_ids[id]] = []
				rsc_locations[self.location_ids[id]].append(rsc_location)
			else:
				con_rule = False
				rsc_location_new = rsc_location.cloneNode(True)

				for rule in rsc_location.getElementsByTagName("rule") :
					id = str(rule.getAttribute("id"))
					if id in self.location_ids.keys():
						if self.location_ids[id] not in rsc_locations.keys():
							rsc_locations[self.location_ids[id]] = []
						#if not con_rule :
						rsc_locations[self.location_ids[id]].append(rsc_location)
						con_rule = True
				
				if con_rule :
					for rule in rsc_location_new.getElementsByTagName("rule") :
						id = str(rule.getAttribute("id"))
						key = self.location_ids[rule.getAttribute("id")]
						if key in self.location.keys() and key in self.location_new.keys():
							if self.location[key]== self.location_new[key]:
			        	                        continue
							if self.location[key] in ['INFINITY', '+INFINITY', "infinity", "+infinity"]:
								if self.location_new[key] in ['INFINITY', '+INFINITY', "infinity", "+infinity"]:
									continue

							if self.location[key] in ['-INFINITY', "-infinity"]:
								if self.location_new[key] in ['-INFINITY', "-infinity"]:
									continue
						if id in self.location_ids.keys():
							 rsc_location_new.removeChild(rule)

					if len(rsc_location_new.getElementsByTagName("rule")) > 0:
						rsc_location_rule.append(rsc_location_new)


		for key in self.nodes:#location.keys():
			if key in self.location.keys() and key in self.location_new.keys():
				if self.location[key]== self.location_new[key]:
        	                        continue
				if self.location[key] in ['INFINITY', '+INFINITY', "infinity", "+infinity"]:
					if self.location_new[key] in ['INFINITY', '+INFINITY', "infinity", "+infinity"]:
						continue

				if self.location[key] in ['-INFINITY', "-infinity"]:
					if self.location_new[key] in ['-INFINITY', "-infinity"]:
						continue
			if key in rsc_locations.keys():
				for loc in rsc_locations[key]:
					try: 
						xml_constraints.removeChild(loc)
					except:
						continue

			if key in self.location_new.keys():
				impl = getDOMImplementation()
				newdoc = impl.createDocument(None, "rsc_location", None)
                	        loc = newdoc.documentElement
                        	loc.setAttribute("id", str("%s-location-on-%s"%(self.rsc, key)))
	                       	loc.setAttribute("node", str(key))
	        		loc.setAttribute("rsc", str(self.rsc))
				loc.setAttribute("score", str(self.location_new[key]))
				xml_constraints.appendChild(loc)

		for loc in rsc_location_rule:
			xml_constraints.appendChild(loc)


                #get old colocations
                rsc_colocations = {}
                for rsc_colocation in manager.xml_nodes["cib"].getElementsByTagName("rsc_colocation") :
                        id = str(rsc_colocation.getAttribute("id"))
                        if id in self.colocation_ids.keys():
                                if self.colocation_ids[id] not in rsc_colocations.keys():
                                        rsc_colocations[self.colocation_ids[id]] = []
                                rsc_colocations[self.colocation_ids[id]].append(rsc_colocation)

                for key in self.resources:
			if key in self.colocation_new.keys():
				if key in self.colocation.keys():
                        		if self.colocation[key] in ['INFINITY', '+INFINITY', "infinity", "+infinity"]:
                                        	continue
					else:
						for coloc in rsc_colocations[key]:
	        	                        	xml_constraints.removeChild(coloc)

	                        impl = getDOMImplementation()
        	                newdoc = impl.createDocument(None, "rsc_colocation", None)
                	        coloc = newdoc.documentElement
                        	coloc.setAttribute("id", str("%s-colocation-on-%s"%(self.rsc, key)))
	                        coloc.setAttribute("rsc", str(self.rsc))
        	                coloc.setAttribute("score", str(self.colocation_new[key]))
				coloc.setAttribute("with-rsc", str(key))
                        	xml_constraints.appendChild(coloc)
			else:
				if key in self.colocation.keys():
					if self.colocation[key] in ['INFINITY', '+INFINITY', "infinity", "+infinity"]:
						for coloc in rsc_colocations[key]:
                                                        xml_constraints.removeChild(coloc)
					else:
						continue
				else:
					continue


		xml_str = xml_constraints.toxml().replace("\n", "")
                manager.cib_do_cmd("cib_replace\n%s\n%s"%(str("constraints"), str(xml_str)))

                if manager.failed_reason != "" :
                        msgbox(top_window, manager.failed_reason)

		return 0

	def save_level(self) :
		if self.level_score == self.level_score_new :
			return
                impl = getDOMImplementation()
                if self.level_score == []:
                        newdoc = impl.createDocument(None, "heartbeatlevel", None)
                        xml_node = newdoc.documentElement
			newdoc = impl.createDocument(None, "meta_attributes", None)
			meta_attribute = newdoc.documentElement
			meta_attribute.setAttribute('id', "heartbeatlevel-options")
			xml_node.appendChild(meta_attribute)
                else :
                        xml_node = self.xml_level[0]
			meta_attribute = xml_node.getElementsByTagName("meta_attributes")[0]
			for child in meta_attribute.childNodes:
				if child.nodeType != xml.dom.Node.ELEMENT_NODE :
                                	continue
				meta_attribute.removeChild(child)

		level = 1
		for score in self.level_score_new :
	                newdoc = impl.createDocument(None, "nvpair", None)
        	        nv = newdoc.documentElement
                	meta_attribute.appendChild(nv)
        	        nv.setAttribute("id", str("heartbeatlevel-options-level%d"%(level)))
                	nv.setAttribute("name", str("level%d"%(level)))
	                nv.setAttribute("value", score)
			level = level + 1

                if self.level_score == [] :
                        xml_str = xml_node.toxml().replace("\n", "")
                        manager.cib_do_cmd("cib_create\n%s\n%s"%(str("configuration"), str(xml_str)))
                elif self.level_score_new == []:
			xml_str = self.xml_level[0].toxml().replace("\n", "")
			manager.cib_do_cmd("cib_delete\n%s\n%s"%("", str(xml_str)))
		else:
                        xml_str = xml_node.toxml().replace("\n", "")
                        manager.cib_do_cmd("cib_replace\n%s\n%s"%(str("heartbeatlevel"), str(xml_str)))

                if manager.failed_reason != "" :
                        msgbox(top_window, manager.failed_reason)
			return

		self.level_score = self.level_score_new

	def callback_changed(self, widget):
		if widget.get_active() != self.is_callback:
			self.is_callback_new = widget.get_active()
			self.changed = True

	def monitor_changed(self, widget):
		if widget.get_active() != self.is_monitor_new:
			self.is_monitor_new = widget.get_active()
			self.changed = True

        def __init__(self, xml_node):
                self.leftview = None
                self.rightview = None
                self.status = None
                self.timer = 0
                self.buf = None

		self.xml_node = xml_node
		self.rsc = str(xml_node.getAttribute('id'))
                global top_window
                dialog = gtk.Dialog(_("Resource %s Location Configuration")%(self.rsc), top_window, gtk.DIALOG_MODAL,
                        (gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK))
                glade = gtk.glade.XML(UI_FILE, "mainnodedlg", "haclient")
                layout = glade.get_widget("mainnodedlg")
                dialog.vbox.add(layout)

		self.first_update = True
		self.changed = False
		#get location widgets
		self.widget_is_callback = glade.get_widget('is_callback')
		self.widget_is_callback.connect("toggled", self.callback_changed)
		self.widget_is_monitor = glade.get_widget('is_monitor')
		self.widget_is_monitor.connect("toggled", self.monitor_changed)

		if self.rsc not in manager.get_top_rsc() or (manager.get_rsc_type(self.rsc) in ["master"]):
			self.widget_is_callback.set_sensitive(False)
		self.widget_is_monitor.set_sensitive(False)

		self.widget_back_node_view = glade.get_widget('backup_node_view')
                renderer1 = gtk.CellRendererText() 
                column1 = gtk.TreeViewColumn(_("Node"), renderer1, text=0)
                renderer2 = gtk.CellRendererText() 
                column2 = gtk.TreeViewColumn(_("Level"), renderer2, text=1)
                self.widget_back_node_view.append_column(column1)
                self.widget_back_node_view.append_column(column2)
		self.widget_back_node_view.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
		self.widget_back_node_view.connect('cursor-changed', self.on_back_node_selected)

		self.widget_del_back_node = glade.get_widget('delete_backnode')
		self.widget_del_back_node.connect('clicked', self.on_del_back_node)
		self.widget_back_node = glade.get_widget('backup_node')
		self.widget_back_node.child.set_editable(False)
		self.widget_add_back_node = glade.get_widget('change_level')
		self.widget_add_back_node.connect('clicked', self.on_add_back_node)
		self.widget_level = glade.get_widget('level')
		self.widget_level.child.set_editable(False)
		self.widget_norun_node = glade.get_widget('other_node')
		self.widget_other_node_label = glade.get_widget('other_node_label')

		#get colocation widgets
		self.widget_left_view = glade.get_widget('leftview')
		renderer = gtk.CellRendererText()   
                column = gtk.TreeViewColumn(_("Resource"), renderer, text=0)
                self.widget_left_view.append_column(column)
		self.widget_left_view.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
		glade.get_widget('delete_left').connect('clicked', self.on_del_view)
		self.widget_colocation_rsc = glade.get_widget('colocation_rsc')
		self.widget_colocation_rsc.child.set_editable(False)
		glade.get_widget('add_colocation').connect('clicked', self.on_add_colocation)

                nodes = manager.get_normal_nodes()
                if nodes != None: 
                        nodes.sort()

                self.nodes = []
                for node in nodes :
                        status = window.judge_node_status(node)
                        if status == -1:
                                continue
                        self.nodes.append(node)


		self.resources = []
		for r in manager.get_top_rsc():
                        if manager.get_rsc_type(r) == "master":
                                continue
			if r != self.rsc :
				self.resources.append(r)

		self.data_init(self.rsc)
		self.update()

                save_top_window = top_window
                top_window = dialog
                while True :
                        ret = dialog.run()
                        if ret in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT] :
                                if self.changed :
                                        ret = confirmbox(top_window, _("The data of current view have been changed.")+"\n"+_("Apply the changes?"),
                                                (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
                                                gtk.STOCK_NO, gtk.RESPONSE_NO,
                                                gtk.STOCK_YES, gtk.RESPONSE_YES))
                                        if ret == gtk.RESPONSE_YES :
                                                self.save()
                                        if ret != gtk.RESPONSE_CANCEL :
                                                top_window = save_top_window
                                                dialog.destroy()
                                                return None
                                else:
                                        top_window = save_top_window
                                        dialog.destroy()
                                        return None
                        else :
                                if self.save() == 0:
	                                top_window = save_top_window
        	                        dialog.destroy()
                	                return None

        def __del__(self):
                if self.timer != 0:
                        gobject.source_remove(self.timer)
                if self.buf != None:
                        self.buf.set_text('')


class Field :
	key = None
	label = None
	default = None
	options = None
	can_be_empty = True
	editable = True
	auto_gen = False
	entry_editable = True
	def __init__(self, key, label=None, default=None, options=None,
			can_be_empty=True, editable=True, auto_gen=False, entry_editable = True) :
		self.key = key
		self.label = cond(label==None, key, label)
		self.default = default
		self.options = options
		self.can_be_empty = can_be_empty
		self.editable = editable
		self.auto_gen = auto_gen
		self.entry_editable = entry_editable

class RAMeta :
	name = ""
	version = None
	desc = ""
	parameters = []
	actions = []

class ElementList:
	store = None
	widget = None
	id_index = None
	idref_index = None

	def __init__(self, obj_types, elem_node_list) :
		treeiter = {}
		attr_is_any_name = False
		elem_is_any_name = False
		id_is_idref = False

		attr_list = []
                sub_obj_list = []
                for obj_type in obj_types :
                    if validate_type == "dtd" :
			self.dtd_elem = manager.get_dtd_elem(obj_type)
			for attr in self.dtd_elem.get_attr_list() :
                               if attr_list.count(attr) == 0 :
                                       attr_list.append(attr)
                        for sub_obj in self.dtd_elem.get_content_model()[1] :
                               if sub_obj_list.count(sub_obj) == 0 :
                                       sub_obj_list.append(sub_obj)
                    else :
			sorted_rng_nodes = manager.sorted_sub_rng_nodes_by_name(obj_type)

			if sorted_rng_nodes != None :
				attr_rng_nodes = sorted_rng_nodes.get("attribute", [])
				elem_rng_nodes = sorted_rng_nodes.get("element", [])
				for rng_node in attr_rng_nodes :
					name = rng_node[0][1].getAttribute("name")
					if name == "" :
						attr_is_any_name = True
					elif attr_list.count(name) == 0 :
						attr_list.append(name)
						if name != "id" :
							continue
						sub_rng_nodes = manager.sorted_sub_rng_nodes_by_node(*rng_node[0])
						for sub_rng_node in sub_rng_nodes.get("data", []) :
							if sub_rng_nodes["data"][0][0][1].getAttribute("type") == "IDREF" :
								id_is_idref = True
								break
				for rng_node in elem_rng_nodes :
					name = rng_node[0][1].getAttribute("name")
					if name == "" :
						elem_is_any_name = True
					elif sub_obj_list.count(name) == 0 :
						sub_obj_list.append(name)
			else :
				attr_is_any_name = True
				elem_is_any_name = True

			if attr_is_any_name :
				for elem_node in elem_node_list :
					for attr_name in elem_node.attributes.keys() :
						if attr_list.count(attr_name) == 0 :
							if attr_name == "id" :
								attr_list.insert(0, attr_name)
							else :
								attr_list.append(attr_name)

		if len(sub_obj_list) > 0 or elem_is_any_name :
			has_elem = True
		else :
			has_elem = False

		self.store = gtk.ListStore(*(tuple(str for i in range(len(attr_list)+1))))
		tree = gtk.TreeView(self.store)
		if len(obj_types) > 1 :
                        visible = True
                else :
                        visible = False
                add_column(tree, _("Type"), 0, self.render_icon, visible=visible)

		for i in range(len(attr_list)) :
			if i == 0 :
				icon_func = self.render_icon
			else :
				icon_func = None

			if attr_list[i] == "id" :
				self.id_index = i + 1
			elif attr_list[i] == "id-ref" :
				self.idref_index = i + 1

			if attr_list[i] == "id" and not id_is_idref and not has_elem :
				visible = False
			else :
				visible = True
			add_column(tree, _(name_cap(attr_list[i])), i+1, icon_func, visible=visible)

		sw = gtk.ScrolledWindow()
		sw.set_shadow_type(gtk.SHADOW_IN)
		sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		sw.add(tree)
		self.widget = sw
		self.tree = tree
		self.attr_list = attr_list

		self.update(elem_node_list)

	def render_icon(self, tvcolumn, cell, model, iter):
		icons = {
				"cluster_property_set": gtk.STOCK_PREFERENCES,
				"node": "node",
				"primitive": gtk.STOCK_DND,
				"group": gtk.STOCK_DND_MULTIPLE,
				"template": gtk.STOCK_DND,
				"clone": gtk.STOCK_COPY,
				"master": gtk.STOCK_COPY,
				"master_slave": gtk.STOCK_COPY,
				"rsc_order": gtk.STOCK_PROPERTIES,
				"rsc_location": gtk.STOCK_PROPERTIES,
				"rsc_colocation": gtk.STOCK_PROPERTIES,
				"rsc_ticket": gtk.STOCK_PROPERTIES,
				"operations": gtk.STOCK_DIALOG_AUTHENTICATION,
				"op": gtk.STOCK_DIALOG_AUTHENTICATION,
				"instance_attributes": gtk.STOCK_PREFERENCES,
				"meta_attributes": gtk.STOCK_PREFERENCES,
				"attributes": gtk.STOCK_PREFERENCES,
				"utilization": gtk.STOCK_PREFERENCES,
				"life_time": gtk.STOCK_INDENT,
				"rule" : gtk.STOCK_JUSTIFY_FILL,
				"expression": gtk.STOCK_MEDIA_STOP,
				"nvpair": gtk.STOCK_MEDIA_STOP,
				"date_expression": gtk.STOCK_JUSTIFY_FILL,
				"transient_attributes": gtk.STOCK_PREFERENCES,
				"date_spec": gtk.STOCK_MEDIA_STOP,
				"duration": gtk.STOCK_MEDIA_STOP,
				"node_state": gtk.STOCK_FIND,
				"lrm": gtk.STOCK_FIND,
				"lrm_resources": gtk.STOCK_DND_MULTIPLE,
				"lrm_resource": gtk.STOCK_DND,
                                "lrm_rsc_op": gtk.STOCK_DIALOG_AUTHENTICATION,
                                "acl_user": gtk.STOCK_ORIENTATION_LANDSCAPE,
                                "acl_role": gtk.STOCK_ORIENTATION_LANDSCAPE,
                                "read": gtk.STOCK_FIND,
                                "write": gtk.STOCK_FIND_AND_REPLACE,
                                "deny": gtk.STOCK_DIALOG_ERROR,
			
			}
		pb = self.tree.render_icon(icons.get(model.get_value(iter, 0), gtk.STOCK_MEDIA_STOP),
			gtk.ICON_SIZE_BUTTON, None)
       		cell.set_property('pixbuf', pb)
		return

	def update(self, elem_node_list) :
		self.elem_node_list = elem_node_list
		self.store.clear()
		self.nodes = {}
		model = self.tree.get_model()
		for elem_node in elem_node_list :
			values = [elem_node.tagName]
			values.extend([elem_node.getAttribute(attr_name) for attr_name in self.attr_list])
			iter = self.store.append(values)
			#elem_type = elem_node.tagName
			#elem_id = elem_node.getAttribute("id")
			#if elem_id == "" :
			#	elem_id = elem_node.getAttribute("id-ref")
			#if elem_id == "" :
			#	elem_id = values[1]
			#if elem_id == "" :
			#	elem_id = elem_node.parentNode.getAttribute("id") 
			#self.nodes[(elem_type, elem_id)] = elem_node

			(node_type, node_id) = self.get_node_key(model, iter)
			self.nodes[(node_type, node_id)] = elem_node

	def get_selected_node(self) :
		(model, iter) = self.tree.get_selection().get_selected()
		if iter != None :
			(node_type, node_id) = self.get_node_key(model, iter)
			return self.nodes.get((node_type, node_id))
		else :
			return None

	def save_iter_status(self, model, path, iter, expand_status):
		(type, id) = self.get_node_key(model, iter)
		expand_status[(type, id)] = self.tree.row_expanded(path)
	
	def restore_iter_status(self, model, path, iter, user_data):
		(select_type, select_id, select_path, expand_status) = user_data
		(type, id) = self.get_node_key(model, iter)
		path = model.get_path(iter)
		if type == select_type and id == select_id :
			self.tree.get_selection().select_iter(iter)
		if expand_status.has_key((type, id)) :
			if expand_status[type, id] :
				self.tree.expand_row(path, False)
			else :
				self.tree.collapse_row(path)
		else :
			self.tree.collapse_row(path)
			
	def save_tree_status(self) :
		(model, iter) = self.tree.get_selection().get_selected()
		if iter != None :
			(select_type, select_id) = self.get_node_key(model, iter)
			select_path = model.get_path(iter)
		else :
			select_type = None
			select_id = None
			select_path = None
		expand_status = {}
		self.store.foreach(self.save_iter_status, expand_status)
		return (select_type, select_id, select_path, expand_status)

	def restore_tree_status(self, tree_status) :
		self.store.foreach(self.restore_iter_status, tree_status)

	def get_node_key(self, model, iter) :
		type = model.get_value(iter, 0)
		id = ""
		if self.id_index != None :
			id = model.get_value(iter, self.id_index)

		if id == "" and self.idref_index != None :
			id = model.get_value(iter, self.idref_index)

		if id == "" :
			id = model.get_value(iter, 1)

		if id == "" and model.iter_parent(iter) != None :
			id = model.get_value(model.iter_parent(iter), 1)

		return (type, id)

class ElementTree(ElementList):
	def __init__(self, obj_types, elem_node_list) :
		self.store = gtk.TreeStore(*(tuple(str for i in range(2))))
		tree = gtk.TreeView(self.store)
		add_column(tree, _("Type"), 0, self.render_icon)
		add_column(tree, _("ID"), 1)

		sw = gtk.ScrolledWindow()
		sw.set_shadow_type(gtk.SHADOW_IN)
		sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		sw.add(tree)
		self.widget = sw
		self.tree = tree

		self.update(elem_node_list)

	def update(self, elem_node_list) :
		self.elem_node_list = elem_node_list
		self.store.clear()
		self.nodes = {}
		for elem_node in elem_node_list :
			iter = self.append_node(None, elem_node)
			self.append_child_nodes(iter, elem_node)

	def append_node(self, iter, node) :
		model = self.tree.get_model()
		node_type = node.tagName
		node_id = node.getAttribute("id")
		values = [node_type, node_id]
		child_iter = self.store.append(iter, values)
		#if node_id == "" :
		#	node_id = node.parentNode.getAttribute("id")
		#self.nodes[(node_type, node_id)] = node
		
		(type, id) = self.get_node_key(model, child_iter)
		self.nodes[(type, id)] = node
		return child_iter

	def append_child_nodes(self, iter, node) :
		for child_node in node.childNodes :
			if child_node.nodeType != xml.dom.Node.ELEMENT_NODE :
				continue
			child_iter = self.append_node(iter, child_node)
			self.append_child_nodes(child_iter, child_node)

class ManageView :
	def __init__(self) :
		vpaned = gtk.VPaned()
		self.widget = vpaned

		top_vbox = gtk.VBox()
		vpaned.add1(top_vbox)

		ui_xml = '''
		<ui>
			<popup name="resource_popup">
				<menuitem action="startrsc"/>
				<menuitem action="stoprsc"/>
				<menuitem action="defaultrsc"/>
				<menuitem action="cleanuprsc"/>
				<menuitem action="migratersc"/>
				<menuitem action="unmigratersc"/>
				<menuitem action="unmanagersc"/>
				<menuitem action="managersc"/>
			</popup>
			<popup action="node_popup">
				<menuitem action="standby"/>
				<menuitem action="active"/>
			</popup>
			<popup action="tools_popup">
				<menuitem action="group-by-node"/>
				<menuitem action="record-pending"/>
				<separator/>
				<menuitem action="refresh"/>
				<menuitem action="reprobe"/>
				<menuitem action="maintenance-mode"/>
			</popup>
			<toolbar name="toolbar">
				<toolitem action="startrsc"/>
				<toolitem action="stoprsc"/>
				<toolitem action="defaultrsc"/>
				<toolitem action="cleanuprsc"/>
				<toolitem action="migratersc"/>
				<toolitem action="unmigratersc"/>
				<toolitem action="unmanagersc"/>
				<toolitem action="managersc"/>
				<separator/>
				<toolitem action="standby"/>
				<toolitem action="active"/>
				<separator/>
				<toolitem action="refresh"/>
				<toolitem action="reprobe"/>
				<toolitem action="maintenance-mode"/>
				<separator/>
				<toolitem action="record-pending"/>
				<toolitem action="group-by-node"/>
			</toolbar>
		</ui>'''

		uimanager = gtk.UIManager()
		actiongroup = gtk.ActionGroup('management')

		if pygtk_newer(2, 6) :
			startrsc_icon = gtk.STOCK_MEDIA_PLAY
			stoprsc_icon = gtk.STOCK_MEDIA_STOP
		else :
			startrsc_icon = "ha-start-resource"
			stoprsc_icon = "ha-stop-resource"

		rsc_actions = [
			('startrsc', startrsc_icon, _('St_art'), None,_('Start resource'), self.on_rsc_action),
			('stoprsc', stoprsc_icon, _('_Stop'), None,_('Stop resource'), self.on_rsc_action),
			('defaultrsc', gtk.STOCK_EXECUTE, _('_Default'), None,_('Work as default'), self.on_rsc_action),
			('cleanuprsc', gtk.STOCK_CLEAR, _('_Cleanup Resource'), None,_('Cleanup resource'), self.on_rsc_cleanup),
			('migratersc', gtk.STOCK_GO_FORWARD, _('Migra_te Resource'), None, _('Migrate a resource to specified node'), 
				self.on_migrate_rsc),
			('unmigratersc', gtk.STOCK_GO_BACK, _('Clea_r Migrate Constraints'),
				None, _('Clear constraints created by migrate'),
				self.on_unmigrate_rsc),
			('unmanagersc', "ha-unmanage-resource", _('_Unmanage Resource'), None, _('Put a resource into unmanaged mode'), 
				self.on_manage_rsc),
			('managersc', "ha-manage-resource", _('_Manage Resource'), None, _('Put a resource into managed mode'), 
				self.on_manage_rsc),
			('refresh', gtk.STOCK_REFRESH, _('Re_fresh Resources'), None, _('Refresh CIB from the LRM status'), 
				self.on_crm_rsc_cmd),
			('reprobe', gtk.STOCK_FIND, _('Re_probe Resources'), None, _('Reprobe for resources started outside of the CRM'), 
				self.on_crm_rsc_cmd),
			]
		node_actions = [
			('standby', "ha-standby-node", _('_Standby'), None,_('Make the node standby'), self.on_standby),
			('active', "ha-active-node", _('_Active'), None,_('Make the node active'), self.on_active)
			]

		toggle_tool_actions = [
			('group-by-node', gtk.STOCK_SORT_DESCENDING, _('_Group By Node'), None, _('Group resources by node'), self.change_group_mode),
			('maintenance-mode', "administration", _('_Maintenance Mode'), None,
				_('Switch to maintenance mode'), self.change_maintenance_mode),
			('record-pending', "record-pending", _('_Indicate Pending Operations'), None,
				_('Indicate pending(starting/stopping) operations'), self.change_record_pending),
			]

		#toolbar = gtk.Toolbar()
		#toolbar.set_orientation(gtk.ORIENTATION_HORIZONTAL)
		#toolbar.set_style(gtk.TOOLBAR_ICONS)
		#self.vbox.pack_start(toolbar, False)

		rsc_action_group = gtk.ActionGroup("rsc_mgmt")
		rsc_action_group.add_actions(rsc_actions)
		self.rsc_action_group = rsc_action_group

		uimanager.insert_action_group(rsc_action_group, 0)

		#for action_entry in rsc_actions :
		#	action_name = action_entry[0]
		#	action = rsc_action_group.get_action(action_name)
		#	tool_item = action.create_tool_item()
		#	toolbar.insert(tool_item, -1)
		#	action.set_accel_group(window.accelgroup)

		#separator = gtk.SeparatorToolItem()
		#toolbar.insert(separator, -1)

		node_action_group = gtk.ActionGroup("node_mgmt")
		node_action_group.add_actions(node_actions)
		self.node_action_group = node_action_group

		uimanager.insert_action_group(node_action_group, 1)

		#for action_entry in node_actions :
		#	action_name = action_entry[0]
		#	action = node_action_group.get_action(action_name)
		#	tool_item = action.create_tool_item()
		#	toolbar.insert(tool_item, -1)
		#	action.set_accel_group(window.accelgroup)

		#separator = gtk.SeparatorToolItem()
		#toolbar.insert(separator, -1)

		self.toggle_tool_action_group = gtk.ActionGroup("toggle_tools")
		self.toggle_tool_action_group.add_toggle_actions(toggle_tool_actions)

		uimanager.insert_action_group(self.toggle_tool_action_group, 2)

		#for action_entry in toggle_tool_actions :
		#	action_name = action_entry[0]
		#	action = self.toggle_tool_action_group.get_action(action_name)
		#	tool_item = action.create_tool_item()
		#	toolbar.insert(tool_item, -1)
		#	action.set_accel_group(window.accelgroup)

		uimanager.add_ui_from_string(ui_xml)
		self.uimanager = uimanager

		toolbar = uimanager.get_widget('/toolbar')
		toolbar.set_style(gtk.TOOLBAR_ICONS)
		top_vbox.pack_start(toolbar, False)

		self.manage_tree = ManageTree()
		top_vbox.pack_start(self.manage_tree.widget)
		self.manage_tree.tree.connect("cursor-changed", self.on_after_show)
		self.manage_tree.tree.connect("event-after", self.on_right_click)

		self.sub_vbox = gtk.VBox()
		vpaned.add2(self.sub_vbox)

		"""notebook =  gtk.Notebook()
		self.notebook = notebook
		vbox.pack_start(notebook, padding=2)

		check_vbox = gtk.VBox()
		check_vbox.set_border_width(5)
		tab_label = gtk.Label(_("Check"))
		notebook.append_page(check_vbox, tab_label)
		self.check_vbox = check_vbox

		scores_vbox = gtk.VBox()
		scores_vbox.set_border_width(5)
		tab_label = gtk.Label(_("Scores"))
		notebook.append_page(scores_vbox, tab_label)
		self.scores_vbox = scores_vbox"""

		self.update()

	def on_right_click(self, widget, event) :
		if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3 :
			menu = None
			(model, iter) = self.manage_tree.tree.get_selection().get_selected()
			cur_type = model.get_value(iter, 0)
			if cur_type in ["node"] :
				menu = self.uimanager.get_widget("/node_popup")
			elif cur_type in ["primitive", "group", "clone", "master"] :
				menu = self.uimanager.get_widget("/resource_popup")
			else :
				menu = self.uimanager.get_widget("/tools_popup")
			menu.popup(None, None, None, event.button, event.time)

	def change_group_mode(self, action) :
		self.update()

	def change_maintenance_mode(self, action) :
		if action.get_active() :
			value = "true"
		else :
			value = "false"

		manager.set_crm_attribute("crm_config", "maintenance-mode", value)
		if manager.failed_reason != "" :
                        msgbox(top_window, manager.failed_reason)

	def change_record_pending(self, action) :
		if action.get_active() :
			value = "true"
		else :
			value = "false"

		manager.set_crm_attribute("op_defaults", "record-pending", value)
                if manager.failed_reason != "" :
                        msgbox(top_window, manager.failed_reason)
                elif value == "true" :
                        manager.record_pending_newly_enabled = True

	def on_after_show(self, treeview = None) :
		for child in self.sub_vbox.get_children() :
			self.sub_vbox.remove(child)

		(model, iter) = self.manage_tree.tree.get_selection().get_selected()
		if iter == None :
			self.update_ui(None, None)
			return

		cur_type = model.get_value(iter, 0)
		cur_status = model.get_value(iter, 2)
		self.update_ui(cur_type, cur_status)

		id = model.get_value(iter, 1)
		if cur_type == "primitive" :
			self.show_rsc_summary(id)
			self.show_operations(id)
		elif cur_type == "cluster" : 
			self.show_sub_attrs(manager.xml_nodes["cib"])
		elif cur_type == "node" :
			for node_state in manager.xml_nodes["cib"].getElementsByTagName("node_state") :
				if node_state.getAttribute("id") == id :
					self.show_sub_attrs(node_state)
					break

	def show_sub_attrs(self, selected_node) :
		if selected_node == None :
			return

		if validate_type == "dtd" :
			dtd_elem = manager.get_dtd_elem(selected_node.tagName)
			attr_list = dtd_elem.get_attr_list()
		else :
			attr_list = []
			is_any_name = False
			sorted_rng_nodes = manager.sorted_sub_rng_nodes_by_name(selected_node.tagName)
			if sorted_rng_nodes != None :
				attr_rng_nodes = sorted_rng_nodes.get("attribute", [])
				for rng_node in attr_rng_nodes :
					name = rng_node[0][1].getAttribute("name")
					if name == "" :
						is_any_name = True
					elif attr_list.count(name) == 0 :
						attr_list.append(name)
			else :
				is_any_name = True

			if is_any_name :
				for attr_name in  selected_node.attributes.keys() :
					if attr_list.count(attr_name) == 0 :
						if attr_name == "id" :
							attr_list.insert(0, attr_name)
						else :
							attr_list.append(attr_name)

		name_labels = {}
		name_label_max_len = 0
		for attr_name in attr_list :
			if attr_name in ["admin_epoch", "num_peers", "cib_feature_revision", "remote_access_port",
						"ccm_transition", "ignore_dtd", "generated", "crm-debug-origin",
						"remote-tls-port", "remote-clear-port", "no-quorum-panic",
						"shutdown", "clear_shutdown"] :
				continue
			attr_value = selected_node.getAttribute(attr_name)
			if attr_value == "" or name_labels.get(attr_name) != None :
				continue
			hbox = gtk.HBox()
			name_label = gtk.Label(_(name_cap(attr_name)+":"))
			name_label.set_alignment(0, 0.5)
			name_label.set_selectable(True)

			name_labels[attr_name] = name_label
			name_label_len = name_label.size_request()[0]
			if name_label_len > name_label_max_len :
				name_label_max_len = name_label_len

			value_label = gtk.Label(attr_value)
			value_label.set_alignment(0, 0.5)
			value_label.set_selectable(True)

			hbox.pack_start(name_label, False, padding=5)
			hbox.pack_start(value_label, False, padding=5)
			self.sub_vbox.pack_start(hbox, False, padding=2)

		for name_label in name_labels.values() :
			name_label.set_size_request(name_label_max_len + 20, -1)

		self.sub_vbox.show_all()

	def show_rsc_summary(self, rsc_id) :
		rsc_summary = {}

		(status, mig_threshold) = manager.get_rsc_status(rsc_id)
		if mig_threshold != "0" :
			rsc_summary["migration-threshold"] = [mig_threshold]

		rsc_summary["fail-count"] = self.get_rsc_failcount(rsc_id)

		name_labels = []
		name_label_max_len = 0
		for attr_name in rsc_summary :
			for i in range(len(rsc_summary[attr_name])) :
				hbox = gtk.HBox()
				if i == 0 :
					name_label = gtk.Label(_(name_cap(attr_name)) + _(":"))
				else :
					name_label = gtk.Label("")
				name_label.set_alignment(0, 0.5)
				name_label.set_selectable(True)

				name_labels.append(name_label)
				name_label_len = name_label.size_request()[0]
				if name_label_len > name_label_max_len :
					name_label_max_len = name_label_len

				value_label = gtk.Label(rsc_summary[attr_name][i])
				value_label.set_alignment(0, 0.5)
				value_label.set_selectable(True)

				hbox.pack_start(name_label, False, padding=5)
				hbox.pack_start(value_label, False, padding=5)
				self.sub_vbox.pack_start(hbox, False, padding=2)

		for name_label in name_labels :
			name_label.set_size_request(name_label_max_len, -1)

		self.sub_vbox.show_all()

	def get_rsc_failcount(self, rsc_id) :
		rsc_summary = []
		for trans_attr_node in manager.xml_nodes["cib"].getElementsByTagName("transient_attributes") :
			node_id = trans_attr_node.getAttribute("id")
			fail_count = ""
			last_failure = ""
			for nv_node in trans_attr_node.getElementsByTagName("nvpair") :
				nv_name = nv_node.getAttribute("name")
				if nv_name.count("fail-count") and nv_name.count(rsc_id) :
					fail_count = nv_node.getAttribute("value")
				elif nv_name.count("last-failure") and nv_name.count(rsc_id) :
					last_failure = nv_node.getAttribute("value")

			if fail_count == "" :
				continue

			summary_str = fail_count
			node_name = manager.node_name(node_id)
			if node_name != "" :
				summary_str += "  (%s, "%node_name
			else :
				summary_str += "  (%s, "%node_id

			if last_failure != "" :
				last_failure_time = time.ctime(float(last_failure))
				if len(summary_str) > 0 :
					summary_str += "  "
				summary_str += _("last failure at \"%s\"")%last_failure_time

			summary_str += ")"

			rsc_summary.append(summary_str)
		return rsc_summary

	def show_operations(self, rsc_id) :
		op_fields = ["Call ID", "Operation", "Interval", "Return Code", "Status", 
				"Last Run", "Exec Time", "Queue Time", "Last Return Code Change"]
			
		store = gtk.TreeStore(*(tuple(str for i in range(len(op_fields)))))
		tree = gtk.TreeView(store)
		for i in range(len(op_fields)) :
			add_column(tree, _(op_fields[i]), i)

		ops = self.get_operations(rsc_id)
		for node_id in ops :
			if len(ops[node_id]) == 0 :
				continue

			node_name = manager.node_name(node_id)
			if node_name == "" :
				node_name = node_id

			node_root = store.append(None, [node_name, "", "", "", "", "", "", "", ""])
			call_ids = [call_id for call_id in ops[node_id]]
			call_ids.sort()
			for call_id in call_ids :
				store.append(node_root, ops[node_id][call_id])
	
		tree.expand_all()

		sw = gtk.ScrolledWindow()
		sw.set_shadow_type(gtk.SHADOW_IN)
		sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		sw.add(tree)

		self.sub_vbox.pack_start(sw)
		self.sub_vbox.show_all()

	def get_operations(self, rsc_id) :
		if validate_type == "dtd" :
			call_id_key = "call_id"
			rc_code_key = "rc_code"
			op_status_key = "op_status"
			last_run_key = "last_run"
			exec_time_key = "exec_time"
			queue_time_key = "queue_time"
			last_rc_change_key = "last_rc_change"
		else :
			call_id_key = "call-id"
			rc_code_key = "rc-code"
			op_status_key = "op-status"
			last_run_key = "last-run"
			exec_time_key = "exec-time"
			queue_time_key = "queue-time"
			last_rc_change_key = "last-rc-change"

		operations = {}
		for lrm_node in manager.xml_nodes["cib"].getElementsByTagName("lrm") :
			node_id = lrm_node.getAttribute("id")
			operations[node_id] = {}
			for lrm_resource_node in lrm_node.getElementsByTagName("lrm_resource") :
				if lrm_resource_node.getAttribute("id") == rsc_id :
					for lrm_rsc_op in lrm_resource_node.getElementsByTagName("lrm_rsc_op") :
						operation = lrm_rsc_op.getAttribute("operation")
						interval = lrm_rsc_op.getAttribute("interval")
						if interval == "0" :
							interval_time = ""
							if operation == "monitor" :
								operation = "probe"
						elif interval == "" :
							interval_time = ""
						else :
							interval_time = interval+"ms"

						rc_code = lrm_rsc_op.getAttribute(rc_code_key)

						if rc_code == "7" and operation == "probe" :
							continue
						elif operation == "notify" :
							continue

						rc_str = manager.lrm_op_rc2str(rc_code)
						if rc_code == "" :
							result_str = rc_str
						else :
							result_str = "%s (rc=%s)"%(rc_str, rc_code)

						call_id = lrm_rsc_op.getAttribute(call_id_key)

						op_status = lrm_rsc_op.getAttribute(op_status_key)
						op_status_str = manager.op_status2str(op_status)

						last_run = lrm_rsc_op.getAttribute(last_run_key)
						if last_run != "" :
							last_run_time = time.ctime(float(last_run))
						else :
							last_run_time = ""

						exec_time = lrm_rsc_op.getAttribute(exec_time_key)
						if exec_time == "" :
							exec_time_str = ""
						else :
							exec_time_str = exec_time + "ms"

						queue_time = lrm_rsc_op.getAttribute(queue_time_key)
						if queue_time == "" :
							queue_time_str = ""
						else :
							queue_time_str = queue_time + "ms"

						last_rc_change = lrm_rsc_op.getAttribute(last_rc_change_key)
						if last_rc_change != "" :
							last_rc_change_time = time.ctime(float(last_rc_change))
						else :
							last_rc_change_time = ""

						operations[node_id][int(call_id)] = [
										call_id,
										operation,
										interval_time,
										result_str,
										op_status_str,
										last_run_time, 
										exec_time_str, 
										queue_time_str,
										last_rc_change_time 
										]
					break
		return operations

	def set_action_sensitive(self, action, sensitive) :
		if self.rsc_action_group.get_action(action) != None :
			self.rsc_action_group.get_action(action).set_property("sensitive", sensitive)
		elif self.node_action_group.get_action(action) != None :
			self.node_action_group.get_action(action).set_property("sensitive", sensitive)

	def update_ui(self, cur_type = None, cur_status = None) :
		all_rsc_type = ["primitive", "group", "clone", "master"]

		self.set_action_sensitive('standby',
			cur_type in ["node"]
			and string.find(cur_status, _("standby")) == -1
			and string.find(cur_status, _("never started")) == -1)

		self.set_action_sensitive('active',
			cur_type in ["node"]
			and string.find(cur_status, _("standby")) != -1
			and string.find(cur_status, _("never started")) == -1)

		self.set_action_sensitive('cleanuprsc',
			cur_type in all_rsc_type)

		self.set_action_sensitive('startrsc',
			cur_type in all_rsc_type)
		
		self.set_action_sensitive('stoprsc',
			cur_type in all_rsc_type)

		self.set_action_sensitive('defaultrsc',
			cur_type in all_rsc_type)

		self.set_action_sensitive('migratersc',
			cur_type in all_rsc_type)

		self.set_action_sensitive('managersc',
			cur_type in all_rsc_type)

		self.set_action_sensitive('unmanagersc',
			cur_type in all_rsc_type)

	def update(self, xml_node = None) :
		view_status = self.save_status()
		self.manage_tree.update(view_status[0])
		self.widget.show_all()
		self.restore_status(view_status)

	def on_rsc_action(self, action) :
		(cur_type, cur_name) = self.manage_tree.get_selected_node()
		if action.get_name() == "startrsc" :
			target_role = "Started"
		elif action.get_name() == "stoprsc" :
			target_role = "Stopped"
		else :
			target_role = "#default"

		if validate_type == "dtd" :
			metaattr_name = "target_role"
		else :
			metaattr_name = "target-role"

                real_rsc_id = cur_name.split(":")[0]
                
                rsc_xml = None
                for resources_node in manager.xml_nodes["cib"].cloneNode(True).getElementsByTagName("resources") :
                        for rsc_node in resources_node.getElementsByTagName(cur_type) :
                                if rsc_node.getAttribute("id") == real_rsc_id :
                                        rsc_xml = rsc_node
                                        break
 
                if rsc_xml == None : 
                        msgbox(top_window, _("Cannot find the %s: %s")%(cur_type, real_rsc_id))
                        return

                supported_rsc_types = manager.get_supported_rsc_types()

                found_nv = False
                clear_all = False
                for nv_xml_node in rsc_xml.getElementsByTagName("nvpair") :
                        if nv_xml_node.getAttribute("name") != metaattr_name :
				continue
                        target_rsc = nv_xml_node
                        while target_rsc.tagName not in supported_rsc_types :
                                target_rsc = target_rsc.parentNode
 
                        target_rsc_id = target_rsc.getAttribute("id")
                        current_value = nv_xml_node.getAttribute("value")
                        
                        if target_rsc_id == real_rsc_id :
                                found_nv = True
                                if target_role == "#default" :
                                        nv_xml_node.parentNode.removeChild(nv_xml_node)
                                else :
                                        nv_xml_node.setAttribute("value", target_role)
                        else :
                                if not clear_all :
                                        retval = confirmbox(top_window, _("Caused by your previous action, this attribute has been set to \"")
                                                +current_value
						+_("\".")+"\n\n"
						+_("Recommended") + _(":")+"\n"
                                                +_("Select \"Clear All\" to remove the attributes for all of the sub-resources.")+"\n"
                                                +_("All of the sub-resources will inherit the attributes from their parent."),
						(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
                                                gtk.STOCK_NO, gtk.RESPONSE_NO,
                                                gtk.STOCK_CLEAR, gtk.RESPONSE_OK,
                                                "Clear All", gtk.RESPONSE_YES),
                                                _("Clear the %s=\"%s\" attribute for sub-resource \"")%(metaattr_name, current_value)
                                                +target_rsc_id+_("\"?"))
                                        if retval in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT] :
                                                return  
                                        if retval in [gtk.RESPONSE_OK, gtk.RESPONSE_YES] :
                                                nv_xml_node.parentNode.removeChild(nv_xml_node)
 
                                        if retval == gtk.RESPONSE_YES :
                                                clear_all = True
                                else :
                                        nv_xml_node.parentNode.removeChild(nv_xml_node)

                if not found_nv and target_role != "#default" :
                        (parent_xml_node, add_obj_type, new_mid_elem) = manager.real_add_obj_type(rsc_xml, "meta_attributes", True)
                        if parent_xml_node == None :
                                msgbox(top_window, _("Cannot %s %s: XML processing error")%(target_role, real_rsc_id))
                                return

                        impl = getDOMImplementation()
                        newdoc = impl.createDocument(None, "nvpair", None)
                        nv = newdoc.documentElement
                        parent_xml_node.appendChild(nv)
                        attr_id = manager.auto_unique_id(nv, metaattr_name)
                        nv.setAttribute("id", attr_id)
                        nv.setAttribute("name", metaattr_name)
                        nv.setAttribute("value", target_role)
 
                xml_str = rsc_xml.toxml().replace("\n", "")
                manager.cib_do_cmd("cib_replace\n%s\n%s"%(str(rsc_xml.tagName), str(xml_str)))
                if manager.failed_reason != "" :
                        msgbox(top_window, manager.failed_reason)

	def on_rsc_cleanup(self, action) :
		(cur_type, cur_name) = self.manage_tree.get_selected_node()
		rsc_list = manager.get_all_rsc()
		if rsc_list == None :
			return
		rsc_options = rsc_list[:]
		rsc_options.insert(0, _("all resources"))

		node_list = manager.get_normal_nodes()
		if node_list == None :
			return
		node_options = node_list[:]
		node_options.insert(0, _("all nodes"))

		cleanup = kvbox(_("Cleanup Resource"), None,
				[Field("rsc", _("Resource"), cur_name, rsc_options, False, entry_editable = False),
				Field("node", _("Node"), _("all nodes"), node_options, False, entry_editable = False)])

		if cleanup != None :
			cleanup_rscs = []
			if cleanup["rsc"] == _("all resources") :
				for rsc in rsc_list :
					if manager.get_rsc_type(rsc) == "primitive" :
						cleanup_rscs.append(rsc)
			elif manager.get_rsc_type(cleanup["rsc"]) != "primitive" :
				all_subrscs = manager.get_all_subrsc(cleanup["rsc"])
				if all_subrscs == None :
					return
				for rsc in all_subrscs :
					if manager.get_rsc_type(rsc) == "primitive" :
						cleanup_rscs.append(rsc)
			else :
				cleanup_rscs.append(cleanup["rsc"])
			
			if cleanup["node"] == _("all nodes") :
				cleanup_nodes = node_list
			else :
				cleanup_nodes = [cleanup["node"]]
					
			for rsc in cleanup_rscs :
				for node in cleanup_nodes :
					#manager.do_cmd("cleanup_rsc\n" + node + "\n" + rsc)
					manager.do_cmd("crm_rsc_cmd\n%s\ncleanup\n%s"%(rsc, node))

	def on_migrate_rsc(self, action) :
		global top_window
		(cur_type, cur_name) = self.manage_tree.get_selected_node()

		dialog = gtk.Dialog(_("Migrate Resource"), top_window, gtk.DIALOG_MODAL,
			(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK))
		dialog.set_border_width(5)
		dialog.set_default_response(gtk.RESPONSE_OK)

		duration_elems = ["yrs", "mths", "wks", "days", "hrs", "mins", "secs"]

		combos = {}
		checkbuttons = {}
		spinbuttons = {}
		name_labels = []
		name_label_max_len = 0	
		for key in ["rsc", "to_node", "force", "duration", "period", "time"] :
			hbox = gtk.HBox()
			if key in ["rsc", "to_node"] :
				name_label = gtk.Label(_(name_cap(key))+_(":"))
				name_label.set_alignment(0, 0.5)
				name_labels.append(name_label)

				name_label_len = name_label.size_request()[0]
				if name_label_len >  name_label_max_len :
					name_label_max_len = name_label_len

				hbox.pack_start(name_label, False, padding=2)

			if key == "rsc" :
				widget = gtk.combo_box_new_text()
				for rsc in manager.get_all_real_rsc() :
					widget.append_text(rsc)

				model = widget.get_model()
				iter = model.get_iter_first()
				while iter != None :
					if model.get_value(iter,0) == manager.obj_real_id(cur_name) :
						widget.set_active_iter(iter)
						break
					iter = model.iter_next(iter)

				combos[key] = widget
				hbox.pack_start(widget, True, padding=2)
			elif key == "to_node" :
				widget = gtk.combo_box_new_text()
				node_list = manager.get_normal_nodes()
				node_options = node_list[:]
				node_options.insert(0, "")
				for node in node_options :
					widget.append_text(node)

				combos[key] = widget
				hbox.pack_start(widget, True, padding=2)
			elif key == "force" :
				widget = gtk.CheckButton(_(name_cap(key)))

				checkbuttons[key] = widget
				hbox.pack_start(widget, True, padding=2)

			elif key == "duration" :
				widget = gtk.CheckButton(_(name_cap(key)))
				checkbuttons[key] = widget
				hbox.pack_start(widget, True, padding=2)
				widget.connect("toggled", self.on_duration_toggled)

			elif key == "period" :
				for key in duration_elems[:4] :
					adj = gtk.Adjustment(0, 00, 99, 1, 3)
					widget = gtk.SpinButton(adj, 0, 0)
					widget.set_width_chars(2)
					widget.set_wrap(True)
					hbox.pack_start(widget, False)
					spinbuttons[key] = widget

					label = gtk.Label(_(name_cap(key)) + " ")
					hbox.pack_start(label, False, padding=2)
					hbox.set_sensitive(False)
					self.period_hbox = hbox

			else :
				for key in duration_elems[4:] :
					adj = gtk.Adjustment(0, 00, 99, 1, 5)
					widget = gtk.SpinButton(adj, 0, 0)
					widget.set_width_chars(2)
					widget.set_wrap(True)
					hbox.pack_start(widget, False)
					spinbuttons[key] = widget

					label = gtk.Label(_(name_cap(key)) + " ")
					hbox.pack_start(label, False, padding=2)
					hbox.set_sensitive(False)
					self.time_hbox = hbox

			dialog.vbox.pack_start(hbox, False, padding=2)
		
		for name_label in name_labels :
			name_label.set_size_request(name_label_max_len, -1)

		widgets = {}
		widgets["combos"] = combos
		widgets["checkbuttons"] = checkbuttons
		widgets["spinbuttons"] = spinbuttons

		widget_group = WidgetGroup(widgets)

		save_top_window = top_window
		top_window = dialog
		dialog.show_all()

		ret = dialog.run()
		if ret in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT] :
			top_window = save_top_window
			dialog.destroy()
			return

		migrate = widget_group.get_values()
		
		top_window = save_top_window
		dialog.destroy()

		period = ""
		if self.period_hbox.get_property("sensitive") :
			for key in duration_elems[:4] :
				if migrate.get(key, "0.0") != "0.0" :
					period += migrate[key].split(".")[0] + key[0].upper()
		time = ""
		if self.time_hbox.get_property("sensitive") :
			for key in duration_elems[4:] :
				if migrate.get(key, "0.0") != "0.0" :
					time += migrate[key].split(".")[0] + key[0].upper()

		if period == "" and time == "" :
			duration = ""
		else :
			duration = "P" + period
			if time != "" :
				duration += "T" + time

		manager.do_cmd("migrate\n%s\n%s\n%s\n%s"
				%(migrate.get("rsc", ""), migrate.get("to_node", ""), migrate.get("force", ""), duration))
		if manager.failed_reason != "" :
			msgbox(top_window, manager.failed_reason.replace("This message can be disabled with -Q", "").replace
				("using the 'crm_resource -U' command or manually with cibadmin", "by \"Clear Migrate Constraints\""))

	def on_duration_toggled(self, widget) :
		 self.period_hbox.set_sensitive(widget.get_active())
		 self.time_hbox.set_sensitive(widget.get_active())

	def on_unmigrate_rsc(self, action) :
		rsc_locations = {}
		for rsc_location in manager.xml_nodes["cib"].getElementsByTagName("rsc_location") :
			id = str(rsc_location.getAttribute("id"))
			rsc_locations[id] = rsc_location
		migrate_ids = {}
		rsc_ids = []
		for id in rsc_locations :
			for prefix in ["cli-prefer-", "cli-standby-", "cli-ban-"] :
				if id.startswith(prefix) :
                                        rsc_id = str(rsc_locations[id].getAttribute("rsc"))
                                        if not migrate_ids.has_key(rsc_id) :
                                                migrate_ids[rsc_id] = []
                                        migrate_ids[rsc_id].append(id)

		all_str = _("all migrated resources")
		rsc_list = migrate_ids.keys()[:]
		rsc_list.insert(0, all_str)

		(cur_type, cur_name) = self.manage_tree.get_selected_node()
		if cur_name in migrate_ids :
			default_option = cur_name
		else :
			default_option = all_str
		unmigrate = kvbox(_("Clear Migrate Constraints"), None,
				[Field("rsc", _("Resource"), default_option, rsc_list, False, entry_editable = False)])

		if unmigrate != None :
			if unmigrate["rsc"] == all_str :
				for rsc_id in migrate_ids.keys() :
					for id in migrate_ids[rsc_id] :
						xml_str = rsc_locations[id].toxml().replace("\n", "")
						manager.cib_do_cmd("cib_delete\nconstraints\n%s"%(str(xml_str)))
			else :
				for id in migrate_ids[unmigrate["rsc"]] :
					xml_str = rsc_locations[id].toxml().replace("\n", "")
					manager.cib_do_cmd("cib_delete\nconstraints\n%s"%(str(xml_str)))

	def on_manage_rsc(self, action) :
		(cur_type, cur_name) = self.manage_tree.get_selected_node()

		if action.get_name() == "managersc" :
			is_managed = "true"
		elif action.get_name() == "unmanagersc" :
			is_managed = "false"
		else :
			is_managed = "#default"

		if validate_type == "dtd" :
			metaattr_name = "is_managed"
		else :
			metaattr_name = "is-managed"

		if is_managed == "#default" :
			manager.do_cmd("del_rsc_attr\n%s\nmeta\n%s"%(manager.obj_real_id(cur_name), metaattr_name))
		else :
			manager.do_cmd("set_rsc_attr\n%s\nmeta\n%s\n%s"%(manager.obj_real_id(cur_name), metaattr_name, is_managed))
			if manager.failed_reason != "" :
				msgbox(top_window, manager.failed_reason)

	def on_crm_rsc_cmd(self, action) :
		global top_window
		cmd = action.get_name()
		node_list = manager.get_normal_nodes()
		if node_list == None :
			node_list = []
		#node_options = node_list[:]
		#node_options.insert(0, "")

		title = _("%s Resources")%_(name_cap(cmd))
		dialog = gtk.Dialog(title, top_window, gtk.DIALOG_MODAL,
			(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK))
		dialog.set_border_width(5)
		dialog.set_default_response(gtk.RESPONSE_OK)

		combos ={}
		for key in ["node"] :
			hbox = gtk.HBox()
			name_label = gtk.Label(_(name_cap(key)) + _(":"))
			name_label.set_alignment(0, 0.5)

			checkbutton = gtk.CheckButton()
			checkbutton.add(name_label)
			hbox.pack_start(checkbutton, False, padding=2)

			value_widget = gtk.combo_box_new_text()
			for node in node_list :
				value_widget.append_text(node)
			value_widget.set_sensitive(False)
			hbox.pack_start(value_widget, True, padding=2)
			combos[key] = value_widget

			checkbutton.connect("toggled", self.on_checkbutton_toggled, value_widget)
			dialog.vbox.pack_start(hbox, False, padding=2)

		widgets = {}
		widgets["combos"] = combos
		widget_group = WidgetGroup(widgets)

		dialog.show_all()

		save_top_window = top_window
		top_window = dialog

		ret = dialog.run()
		if ret in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT] :
			top_window = save_top_window
			dialog.destroy()
			return

		cmd_args = widget_group.get_values()
		top_window = save_top_window
		dialog.destroy()

		#cmd_args = kvbox(_("%s Resources")%_(name_cap(cmd)), None,
		#		[Field("node", _("Node"), "", node_options, True, entry_editable = False)])

		#if cmd_args == None :
		#	return

		manager.do_cmd("crm_rsc_cmd\n\n%s\n%s"%(cmd, cmd_args.get("node", "")))
		if manager.failed_reason != "" :
			msgbox(top_window, manager.failed_reason)

	def on_checkbutton_toggled(self, checkbutton, widget) :
		widget.set_sensitive(checkbutton.get_active())

	def on_standby(self, action) :
		(cur_type, cur_name) = self.manage_tree.get_selected_node()
		if confirmbox(top_window, _("Make") +" " +cur_name + " " +_("standby")+"?") == gtk.RESPONSE_YES:
			#manager.do_cmd("standby\n"+cur_name + "\n" + "on")
			manager.do_cmd("crm_attribute\nnodes\nset\nstandby\non\n%s\n\n"%cur_name)
			if manager.failed_reason != "" :
				msgbox(top_window, manager.failed_reason)

	def on_active(self, action) :
		(cur_type, cur_name) = self.manage_tree.get_selected_node()
		if confirmbox(top_window, _("Make") +" " +cur_name + " " + _("active")+"?") == gtk.RESPONSE_YES :
			#manager.do_cmd("standby\n"+cur_name + "\n" + "off")
			manager.do_cmd("crm_attribute\nnodes\nset\nstandby\noff\n%s\n\n"%cur_name)
			if manager.failed_reason != "" :
				msgbox(top_window, manager.failed_reason)

	def save_status(self) :
		group_by_node = self.toggle_tool_action_group.get_action("group-by-node").get_active()
		tree_status = self.manage_tree.save_tree_status()
		paned_position = self.widget.get_position()
		return (group_by_node, tree_status, paned_position)

	def restore_status(self, view_status) :
		#if view_status == None :
		#	return
		(group_by_node, tree_status, paned_position) = view_status
		if group_by_node :
			self.toggle_tool_action_group.get_action("group-by-node").set_active(group_by_node)

		self.update_tool_button()
		self.manage_tree.restore_tree_status(tree_status)
		self.on_after_show()

		if paned_position :
			(paned_width, paned_height) = self.widget.size_request()
			self.manage_tree.widget.set_size_request(paned_width, paned_position)
			self.widget.set_position(paned_position)

	def update_tool_button(self) :
		#value = manager.do_cmd("crm_attribute\ncrm_config\nget\nmaintenance-mode\n\n\n\n")
		#if value != None and len(value) > 0 and value[0].count("true") :
		value = manager.find_attribute("crm_config", "maintenance-mode")
		action = self.toggle_tool_action_group.get_action("maintenance-mode")
		if pygtk_newer(2, 10) and pygobject_newer(2, 12, 3) :
			action.disconnect_by_func(self.change_maintenance_mode)

		if value == "true" :
			if not action.get_active() :
				action.set_active(True)
		else :
			if action.get_active() :
				action.set_active(False)

		if pygtk_newer(2, 10) and pygobject_newer(2, 12, 3) :
			action.connect("toggled", self.change_maintenance_mode)

		#value = manager.do_cmd("crm_attribute\nop_defaults\nget\nrecord-pending\n\n\n\n")
		#if value != None and len(value) > 0 and value[0].count("true") :
		value = manager.find_attribute("op_defaults", "record-pending")
		action = self.toggle_tool_action_group.get_action("record-pending")
		if pygtk_newer(2, 10) and pygobject_newer(2, 12, 3) :
			action.disconnect_by_func(self.change_record_pending)

		if value == "true" :
			if not action.get_active() :
				action.set_active(True)
		else :
			if action.get_active() :
				action.set_active(False)

		if pygtk_newer(2, 10) and pygobject_newer(2, 12, 3) :
			action.connect("toggled", self.change_record_pending)

class ManageTree :
	store = None
	tree = None
	last_iter = None
	def __init__(self) :
		global top_window
		treeiter = {}
		self.store = gtk.TreeStore(str, str, str, str)

		tree = gtk.TreeView(self.store)
		add_column(tree, _("Type"), 0, self.render_type_icon, visible=False)
		add_column(tree, _("Name"), 1, self.render_type_icon)
		add_column(tree, _("Status"), 2, self.render_status_icon)
		add_column(tree, _("Details"), 3)
		(window_width, window_height) = top_window.get_size()
		tree.set_size_request(500, window_height / 2)
		#tree.connect("cursor-changed", self.on_cursor_changed, tree.get_selection())
		#tree.connect("event-after", self.on_right_click)

		sw = gtk.ScrolledWindow()
		sw.set_shadow_type(gtk.SHADOW_IN)
		sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		sw.add(tree)
		self.widget = sw
		self.tree = tree

	def get_selected_node(self):
		(model, iter) = self.tree.get_selection().get_selected()
		type = model.get_value(iter, 0)
		name = model.get_value(iter, 1)
		return (type, name)

	def render_type_icon(self, tvcolumn, cell, model, iter) :
		icons = {
			"cluster": "nodes",
			"node": "node", 
			"resources": gtk.STOCK_DIRECTORY,
			"inactive resources": gtk.STOCK_DIRECTORY,
			"primitive": gtk.STOCK_DND,
			"group": gtk.STOCK_DND_MULTIPLE,
			"clone": gtk.STOCK_COPY,
			"master": gtk.STOCK_COPY,
			"master_slave": gtk.STOCK_COPY,
			}
		pb = self.tree.render_icon(icons.get(model.get_value(iter, 0), gtk.STOCK_MEDIA_STOP),
			gtk.ICON_SIZE_BUTTON, None)
		cell.set_property('pixbuf', pb)
		return
	
	def render_status_icon(self, tvcolumn, cell, model, iter):
 		icons = {-2:"stopped",
			 -1:gtk.STOCK_PREFERENCES,
			  0:"running",
			  1:"stopped",
			  2:"dirty-stopped",
			  3:"failed",
			  4:"starting",
			  5:"stopping"}
		status = self.iter_status(model,iter)
		pb = self.tree.render_icon(icons[status],
			gtk.ICON_SIZE_SMALL_TOOLBAR, None)
       		cell.set_property('pixbuf', pb)
		return

	def iter_status(self, model, iter) :
		# -1:config 0: ok, 1: stopped, 2: umanaged, 3:failed, 4:stop failed
		type = model.get_value(iter, 0)
		status = model.get_value(iter, 2)
		iter_status = 0
		if type == "primitive" :
			if string.find(status, _("unmanaged")) != -1 \
					or string.find(status, _("unclean")) != -1 \
					or string.find(status, _("failure ignored")) != -1 :
				iter_status = 2
			elif string.find(status, _("failed")) != -1 :
				iter_status = 3
			elif string.find(status, _("starting")) != -1 :
				iter_status = 4
			elif string.find(status, _("stopping")) != -1 :
				iter_status = 5
			elif string.find(status, _("not running")) != -1 :
				iter_status = 1
			elif string.find(status, _("running")) != -1 :
				iter_status = 0
			else :
				iter_status = 2
		
		elif type == "node" :
			if status == _("ping node") :
				iter_status = -1				
			elif string.find(status, _("online")) != -1 :
				iter_status = 0
			else :
				iter_status = 1
		elif type in ["group","resources","clone","master"]:
			iter_status = 0
		else :
			iter_status = -2
		if model.iter_has_child(iter) :
			for i in range(0, model.iter_n_children(iter)) :
				child = model.iter_nth_child(iter,i)
				child_status = self.iter_status(model, child)
				if child_status > iter_status :
					iter_status = child_status
		
		return iter_status

	def save_iter_status(self, model, path, iter, expand_status):
		type = model.get_value(iter, 0)
		name = model.get_value(iter, 1)
		expand_status[(type, name)] = self.tree.row_expanded(path)
	
	def restore_iter_status(self, model, path, iter, user_data):
		(select_name, select_type, select_path, expand_status) = user_data
		type = model.get_value(iter, 0)
		name = model.get_value(iter, 1)
		path = model.get_path(iter)
		if name == select_name and type == select_type :
			self.tree.get_selection().select_iter(iter)
		if expand_status.has_key((name,type)) :
			if expand_status[name, type] :
				self.tree.expand_row(path, False)
			else :
				self.tree.collapse_row(path)
		else :
			self.tree.expand_row(path, False)
			
	def save_tree_status(self) :
		(model, iter) = self.tree.get_selection().get_selected()
		if iter != None :
			select_type = model.get_value(iter, 0)
			select_name = model.get_value(iter, 1)
			select_path = model.get_path(iter)
		else :
			select_name = None
			select_type = None
			select_path = None
		expand_status = {}
		self.store.foreach(self.save_iter_status, expand_status)
		return (select_name, select_type, select_path, expand_status)

	def restore_tree_status(self, tree_status) :
		self.store.foreach(self.restore_iter_status, tree_status)
		(name, type, path, expand_status) = tree_status
		if  name == None :
			self.tree.get_selection().select_path((0,))
			self.tree.expand_all()
		
	def update(self, group_by_node = False) :
		self.store.clear()
		if not manager.connected :
			return
		
		nodes = manager.get_all_nodes()
		if nodes == None :
			return

		active_nodes = manager.get_active_nodes()
		if active_nodes == None :
			return

		crm_nodes = manager.get_crm_nodes()
		if crm_nodes == None :
			return
		
		have_quorum = False
		for attr_name in ["have-quorum", "have_quorum"] :
			attr_value = manager.xml_nodes["cib"].getAttribute(attr_name)
			if attr_value != "" :
				if attr_value in ["true", "yes", "1"] :
					have_quorum = True
				break
		if have_quorum :
			status = _("have quorum")
		else :
			status = _("no quorum")
		
		cluster_type = manager.get_cluster_type().capitalize()
		if len(cluster_type) > 0 :
			cluster_type += " & Pacemaker"
		else :
			cluster_type += "Pacemaker"

		#root = self.store.append(None, ["cluster", cluster_type, status, ""])
		
		if group_by_node :
			nodes_root = self.store.append(None, ["cluster", _("Cluster"), status, cluster_type])
			for node in nodes :
				self.add_node(nodes_root, node, node in active_nodes, node in crm_nodes)
			inactive_root = self.store.append(None, ["inactive resources", _("Inactive resources"), "", ""])
			rscs = manager.get_all_rsc()
			for rsc in rscs :
				rsc_type = manager.get_rsc_type(rsc)
				if rsc_type != "primitive" :
					continue
				nodes = manager.get_rsc_running_on(rsc)
				if nodes != None and len(nodes) > 0 :
					continue 
				else :
					(status, mig_threshold) = manager.get_rsc_status(rsc)
					info = self.get_rsc_info(rsc)
					self.store.append(inactive_root,[rsc_type, rsc, _(status), info])
		else :
			nodes_root = self.store.append(None, ["cluster", _("Cluster"), status, cluster_type])
			for node in nodes :
				self.add_node(nodes_root, node, node in active_nodes, node in crm_nodes, False)
			rscs_root = self.store.append(None, ["resources", _("Resources"), "", ""])
			rscs = manager.get_top_rsc()
			for rsc in rscs :
				self.add_rsc(rscs_root, rsc)
		
	def add_rsc(self, parent, rsc) :
		type = manager.get_rsc_type(rsc)
		status = ""
		label = ""
		if type == "primitive" :
			(status, mig_threshold) = manager.get_rsc_status(rsc)
			nodes = manager.get_rsc_running_on(rsc)
			info = self.get_rsc_info(rsc)
			if nodes != None and len(nodes)>0:
				self.store.append(parent,[type, rsc, _(status) + _(" on ")+str(nodes), info])
			else :
				self.store.append(parent,[type, rsc, _(status), info])
				
		elif type in ["group","clone","master"] :
			status = type
			iter = self.store.append(parent,[type, rsc, _(status), ""])
			for subrsc in manager.get_sub_rsc(rsc) :
				self.add_rsc(iter, subrsc)

	def get_rsc_info(self, rsc_id) :
		for lrm_rsc_node in manager.xml_nodes["cib"].getElementsByTagName("lrm_resource") :
			if lrm_rsc_node.getAttribute("id") == rsc_id :
				rsc_class = lrm_rsc_node.getAttribute("class")
				if rsc_class != "" :
					rsc_info = rsc_class + "::"
				else :
					rsc_info = ""

				rsc_provider = lrm_rsc_node.getAttribute("provider")
				if rsc_provider != "" :
					rsc_info += rsc_provider + ":"

				rsc_type = lrm_rsc_node.getAttribute("type")
				rsc_info += rsc_type
				return rsc_info
		return ""
					
	def add_node(self, nodes_root, node, active, started, add_rscs = True):
		status = _("unknown")
		if not started :
			node_type = manager.get_nodetype(node)
			if  node_type == "normal" :
				status = _("never started")
			elif node_type == "ping" :
				status = _("ping node")
			else :
				status = _("unknown type")
		else :
			node_status = manager.get_node_config(node)
			if node_status.get("online") == "True" :
				status = _("online")
			elif node_status.get("pending") == "True" :
				status = _("pending")
			else :
				status = _("offline")

			if node_status.get("unclean") == "True" :
				status += " (" + _("unclean") + ")"

			if node_status.get("is_dc") == "True" :
				status += " (" + _("dc") + ")"

			if node_status.get("standby_onfail") == "True" \
					and node_status.get("online") == "True" :
				status += " - " + _("standby") + " (" + _("on-fail") + ")"
			elif node_status.get("standby") == "True" :
				status += " - " + _("standby")

		node_iter = self.store.append(nodes_root,["node", node, status, ""])

		if add_rscs :
	 		running_rsc = manager.get_running_rsc(node)
 			for rsc in running_rsc :
 				self.add_rsc(node_iter, rsc)

class MainTree(ElementList) :
	#neoshineha ming.liu
        def on_right_click(self, widget, event) :
                if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3 :
                        menu = None
			#["crm_config", "nodes", "resources", "constraints", "status", "rsc_defaults", "op_defaults"]
			if window.cur_type == "nodes" :
                                menu = window.uimanager.get_widget("/node_popup")
                        elif window.cur_type == "cluster" or window.cur_type == None:
                                menu = window.uimanager.get_widget("/connection_popup")
                        elif window.cur_type == _("primitive"):
                                menu = window.uimanager.get_widget("/resource_popup")
                        elif window.cur_type == "resources":
                                menu = window.uimanager.get_widget("/global_popup")
                        else :
                                menu = window.uimanager.get_widget("/group_popup")
                        menu.popup(None, None, None, event.button, event.time)

        def get_selected_node(self):
                (model, iter) = self.tree.get_selection().get_selected()
                type = model.get_value(iter, 2)
                name = model.get_value(iter, 0)
                return (type, name)
	#neoshineha end ming.liu

	def __init__(self) :
		obj_type = "cib"
		self.store = gtk.TreeStore(str, str, str)

		widget = gtk.TreeView(self.store)
		#widget.set_headers_visible(False)
		add_column(widget, None, 0, self.render_icon)
		title_label = gtk.Label()
		#neoshineha add ming.liu
		title_label.set_text(_("Name"))
		title_label.show()
		widget.get_column(0).set_widget(title_label)
                add_column(widget, None, 1)
                title_label2 = gtk.Label()
                title_label2.set_text(_("Status"))
                title_label2.show()
                widget.get_column(1).set_widget(title_label2)
		#neoshineha end ming.liu

		widget.set_size_request(180, 200)
		widget.connect("cursor-changed", self.on_cursor_changed, widget.get_selection())
		widget.connect("event-after", self.on_right_click)
		widget.connect("row-collapsed", self.update_table)
		widget.connect("row-expanded", self.update_table)
		self.tree = widget
		self.widget = widget
		self.title_label = title_label

	def update_table(self, widget, iter, path):
		window.select_view(None, None, None)
		return

	def on_cursor_changed(self, treeview, selection) :
		try :
			if not window.can_change_view() :
				if self.last_iter != None :
					selection.select_iter(self.last_iter)
					return
		except :
			pass

		(model, iter) = selection.get_selected()

		if window.cur_type != None and window.cur_view != None :
			window.view_status[window.cur_type] = window.cur_view.save_status()

		if iter == None :
			window.select_view(None, None, None)
			return

		self.row_num = 0
		self.get_row(model, treeview, model.get_iter_first(), iter)

		type = model.get_value(iter, 2)
		name = model.get_value(iter, 0)
		#type = model.get_value(iter, 1)
		status = model.get_value(iter, 1)
		window.select_view(type, name, status)
		self.last_iter = iter



	def get_row(self, model, treeview, root, iter):#return the path from parent to current iter
		if root == None :
			return
		if model.get_path(root) == model.get_path(iter):
			global selected_row_num
			selected_row_num = self.row_num
			return
		self.row_num += 1
		if not treeview.row_expanded(model.get_path(root)):
			return
		else:
			child = model.iter_children(root)
			while child != None and child != iter:
				self.get_row(model, treeview, child, iter)
				child = model.iter_next(child)

		return


	def render_icon(self, tvcolumn, cell, model, iter):
		name = model.get_value(iter, 0)
		stocks = {
				"cib":  gtk.STOCK_HARDDISK,
				"configuration": gtk.STOCK_HARDDISK,
				"status": gtk.STOCK_FIND,
				"crm_config": gtk.STOCK_PREFERENCES,
				"op_defaults": gtk.STOCK_PREFERENCES,
				"rsc_defaults": gtk.STOCK_PREFERENCES,
				"nodes": "nodes",
				"resources": gtk.STOCK_DIRECTORY,
				"constraints": gtk.STOCK_PROPERTIES,
				"acls": gtk.STOCK_DIALOG_AUTHENTICATION,
				"management" : gtk.STOCK_EXECUTE
			}
 		icons = {-2:gtk.STOCK_DIALOG_INFO,
			 -1:gtk.STOCK_PREFERENCES,
			  0:gtk.STOCK_YES,
			  1:gtk.STOCK_DIALOG_INFO,
			  2:gtk.STOCK_DIALOG_WARNING,
			  3:gtk.STOCK_DIALOG_ERROR}
		status = self.iter_status(model,iter)
		#neoshineha ming.liu
		pb = self.widget.render_icon(icons[status],
			gtk.ICON_SIZE_BUTTON, None)
		#neoshineha end ming.liu

       		cell.set_property('pixbuf', pb)
		#cell.set_fixed_size(10,10)
		cell.set_property("height",29)
		return

	def iter_status(self, model, iter) :
		#return 0
		# -1:config 0: ok, 1: stopped, 2: umanaged, 3:failed, 4:stop failed
		type = model.get_value(iter, 2)
		status = model.get_value(iter, 1)
		iter_status = 0
		if type == _("primitive") :
			if string.find(status, _("not running")) != -1 :
				iter_status = 1
			elif string.find(status, _("running")) != -1 :
				iter_status = 0
			elif string.find(status, _("fail")) != -1 :
				iter_status = 3
			else :
				iter_status = 2
		
		elif type == "node" :
			if status == _("ping node") :
				iter_status = -1				
			elif string.find(status, _("running")) != -1 :
				iter_status = 0
			else :
				iter_status = 1
		elif type in [_("group"),_("resources"),_("clone"),_("master")]:
			iter_status = 0
		elif type in [_("orders"),_("locations"), _("colocations")] :
			iter_status = -1
		else :
			iter_status = -2
		if model.iter_has_child(iter) :
			for i in range(0, model.iter_n_children(iter)) :
				child = model.iter_nth_child(iter,i)
				child_status = self.iter_status(model, child)
				if child_status > iter_status :
					iter_status = child_status
		
		return iter_status
		
	def update(self) :
		tree_status = self.save_tree_status()

		#self.title_label.set_text("")
		self.store.clear()
		if not manager.connected :
			window.select_view(None, None, None)
			return

		'''if manager.active_cib == "" :
			title_str = _("Live")
		else :
			title_str = _("Shadow: ") + manager.active_cib

		self.title_label.set_markup('<b>'+title_str+'</b>')'''

		self.treeiter = {}
		'''if validate_type == "dtd" :
			self.dtd_elem = manager.get_dtd_elem("cib")
			for (name, mod) in self.dtd_elem.get_content_model()[1] :
				if mod == '' :
					if mode_level != 2 and name == "status" :
						continue
					treeiter[name] = self.store.append(None, [_(name_cap(name)), name, "aaaaa"])
					sub_dtd_elem = manager.get_dtd_elem(name)
					for (sub_name, sub_mod) in sub_dtd_elem.get_content_model()[1] :
						if sub_mod == '' :
							treeiter[sub_name] =  \
								self.store.append(treeiter[name], [_(name_cap(sub_name)), sub_name, "aaaa"])
		else :
			sorted_rng_nodes = manager.sorted_sub_rng_nodes_by_name("cib")
			for rng_node in sorted_rng_nodes.get("element", []) :
					name = rng_node[0][1].getAttribute("name")
					if mode_level != 2 and name == "status" :
						continue
					treeiter[name] = self.store.append(None, [_(name_cap(name)), name, "aaaaa"])
					sub_rng_nodes = manager.sorted_sub_rng_nodes_by_node(*rng_node[0])
					for sub_rng_node in sub_rng_nodes.get("element", []) :
						if manager.find_decl(sub_rng_node, "zeroOrMore") != 0 :
							continue
						sub_name = sub_rng_node[0][1].getAttribute("name")
						treeiter[sub_name] =  \
							self.store.append(treeiter[name], [_(name_cap(sub_name)), sub_name, "aaaaa"])
					

			#(u',', [(u'configuration', ''), (u'status', '')], '')
		if manager.active_cib == "" :
			treeiter["management"] = self.store.append(None, [_("Management"), "management", "aaaaa"])'''
		
                #neoshineha ming.liu
                nodes = manager.get_all_nodes()
                if nodes == None : 
                        return

                active_nodes = manager.get_active_nodes()
                if active_nodes == None :
                        return

                crm_nodes = manager.get_crm_nodes()
                if crm_nodes == None :
                        return

                have_quorum = False
                for attr_name in ["have-quorum", "have_quorum"] :
                        attr_value = manager.xml_nodes["cib"].getAttribute(attr_name)
                        if attr_value != "" :
                                if attr_value in ["true", "yes", "1"] :
                                        have_quorum = True
                                break
                if have_quorum :
                        status = _("have quorum")
                else :
                        status = _("no quorum")

		root = None
                rsc_root = self.store.append(root, [_("Resources"),status, "resources"])
                rscs = []

                #rscs = manager.get_top_rsc()
                rscs = []
                group_nodes = manager.xml_nodes["cib"].getElementsByTagName("resources")[0]
                for child in group_nodes.childNodes :
                                if child.nodeType != child.ELEMENT_NODE :
                                        continue
                                rscs.append(str(child.getAttribute('id')))
				self.add_rsc(rsc_root, child)

                #neoshineha end ming.liu

		self.restore_tree_status(tree_status)
		(type, id, path, expand_status) = tree_status
		if expand_status == {} :
			self.widget.expand_all()

		selection = self.widget.get_selection()
		(model, iter) = selection.get_selected()
		if not (iter != None and window.cur_view != None and window.cur_type.count("crm_config") == 0 ):
			self.on_cursor_changed(self.widget, self.widget.get_selection())
		'''	cur_xml_nodes = manager.xml_nodes["cib"].getElementsByTagName(window.cur_type)
			if len(cur_xml_nodes) > 0 :
				cur_xml_node = cur_xml_nodes[0] 
			else :
				cur_xml_node = window.cur_type
			window.cur_view.update(cur_xml_node)
		else :
			if iter == None :
				if manager.active_cib == "" :
					selection.select_iter(self.treeiter["management"])
				else :
					selection.select_path("0")
			self.on_cursor_changed(self.widget, self.widget.get_selection())'''
		
	#neoshineha ming.liu
        def add_rsc(self, parent, rsc) :
		if str(type(rsc)) == "<type 'str'>" :
			rsc_type = manager.get_rsc_type(rsc)
			name = str(rsc)
		else:
                	rsc_type = rsc.tagName
			name = str(rsc.getAttribute("id"))
                status = ""
                label = ""
                if rsc_type == "primitive" :
                        label = _("primitive")
                        status = manager.get_rsc_status(name)
                        nodes = manager.get_rsc_running_on(name)
                        if status != None and len(status)>0 :
	                        if nodes != None and len(nodes)>0 :
        	                        self.store.append(parent,[name, _(status[0]) + _(" on ")+str(nodes[0]), label])
                	        else :
                        	        self.store.append(parent,[name, _(status[0]), label])
			else:
                        	self.store.append(parent,[name, "", label])

                elif rsc_type in ["group"] :
                        label = rsc_type
                        status = rsc_type
                        iter = self.store.append(parent,[name, _(status[0]), _(label)])

                        for subrsc in manager.get_sub_rsc(name) :
                                self.add_rsc(iter, subrsc)
	                #for child in rsc.childNodes :
                        #        if child.nodeType != child.ELEMENT_NODE :
                        #                continue
                        #        self.add_rsc(iter, child)

                elif rsc_type in ["clone","master"] :
			label = rsc_type
                        status = rsc_type
                        iter = self.store.append(parent,[name, _(status), _(label)])
                        for subrsc in manager.get_sub_rsc(name) :
                                self.add_rsc(iter, subrsc)

	#neoshineha end ming.liu

class ClusterView :
	def update(self, xml_node = None) :
		self.cluster_info_labels = None
		self.cib_attrs_labels = None
		for line in self.cluster_info_vbox.get_children() :
			self.cluster_info_vbox.remove(line)
		for line in self.cib_attrs_vbox.get_children() :
			self.cib_attrs_vbox.remove(line)

		self.widget.show_all()

		config = manager.get_cluster_config()
		if config == None or len(config) == 0 :
			self.widget.get_nth_page(0).hide_all()
		else :	
			cluster_info_labels= {}
			for key in config.keys():
				if config.get(key, "") == "" :
					continue
				cluster_info_labels[key] = self.add_line(self.cluster_info_vbox, config.get(key,""))
			self.cluster_info_labels = cluster_info_labels
			self.widget.get_nth_page(0).show_all()

		xml_node = manager.xml_nodes.get("cib")
		if xml_node == None :
			self.widget.get_nth_page(1).hide_all()
		else :
			obj_type = xml_node.tagName
			if validate_type == "dtd" :
				dtd_elem = manager.get_dtd_elem(obj_type)
				attr_names = dtd_elem.get_attr_list()
			else :
				sorted_rng_nodes = manager.sorted_sub_rng_nodes_by_name("cib")
				attr_node_list = sorted_rng_nodes.get("attribute", [])
				attr_names = [attr_node[0][1].getAttribute("name") for attr_node in attr_node_list]

			cib_attrs_labels = {}
			for attr_name in attr_names :
				attr_value = xml_node.getAttribute(attr_name)
				if attr_value == "" :
					continue
				cib_attrs_labels[attr_name] = self.add_line(self.cib_attrs_vbox, attr_value)
			self.cib_attrs_labels = cib_attrs_labels
			self.widget.get_nth_page(1).show_all()

		self.on_after_show()

	def add_line(self, vbox, value) :
		hbox = gtk.HBox()
		name_label = gtk.Label()
		name_label.set_alignment(0, 0.5)
		name_label.set_selectable(True)
		eventbox = gtk.EventBox()
		eventbox.add(name_label)

		value_label = gtk.Label(value)
		value_label.set_alignment(0, 0.5)
		value_label.set_selectable(True)

		hbox.pack_start(eventbox, False, padding=5)
		hbox.pack_start(value_label, False, padding=5)
		vbox.pack_start(hbox, False, padding=2)

		return name_label

	def on_after_show(self) :
		info_dict =	{
				"quorum_server":	"Quorum Server",
				"use_logd":		"Use Logd",
				"autojoin":		"Auto Join",
				"apiauth":		"API Authentication",
				"auto_failback":	"Auto Failback",
				"baud":			"Baud Rate",
				"debug":		"Debug Level",
				"debugfile":		"Debug File",
				"deadping":		"Dead Ping",
				"deadtime":		"Dead Time",
				"hbversion":		"Heartbeat Version",
				"hopfudge":		"Hop Fudge",
				"initdead":		"Initial Dead Time",
				"keepalive":		"Keep Alive",
				"logfacility":		"Log Facility",
				"logfile":		"Log File",
				"msgfmt":		"Message Format",
				"nice_failback":	"Nice Failback",
				"node":			"Node",
				"normalpoll":		"Normal Poll",
				"stonith":		"Stonith",
				"udpport":		"UDP Port",
				"warntime":		"Warning Time",
				"watchdog":		"Watchdog",
				"cluster":		"Cluster"
				}


		if self.cluster_info_labels != None :
			cluster_type = manager.get_cluster_type()
			if cluster_type == "openais" :
				target_site = "www.openais.org"
			elif cluster_type == "heartbeat" :
				target_site = "www.linux-ha.org"
			else :
				target_site = "www.clusterlabs.org"

			name_label_max_len = 0
			for key in self.cluster_info_labels.keys() :
				make_label_active(self.cluster_info_labels[key], _(info_dict.get(key, key))+_(":"), target_site)
				name_label_len = self.cluster_info_labels[key].size_request()[0]
				if name_label_len >  name_label_max_len :
					name_label_max_len = name_label_len

			for name_label in self.cluster_info_labels.values() :
				name_label.set_size_request(name_label_max_len, -1)

		if self.cib_attrs_labels != None :
			target_site = "www.clusterlabs.org"
			name_label_max_len = 0
			for key in self.cib_attrs_labels.keys() :
				make_label_active(self.cib_attrs_labels[key], _(name_cap(key)+":"), target_site)
				name_label_len = self.cib_attrs_labels[key].size_request()[0]
				if name_label_len >  name_label_max_len :
					name_label_max_len = name_label_len

			for name_label in self.cib_attrs_labels.values() :
				name_label.set_size_request(name_label_max_len, -1)
			
	def __init__(self) :
		notebook =  gtk.Notebook()
		self.notebook = notebook
		self.widget = notebook

		cluster_info_vbox = gtk.VBox()
		cluster_info_vbox.set_border_width(5)
		tab_label = gtk.Label(_("Cluster"))
		notebook.append_page(cluster_info_vbox, tab_label)
		self.cluster_info_vbox = cluster_info_vbox

		cib_vbox = gtk.VBox()
		cib_vbox.set_border_width(5)
		tab_label = gtk.Label(_("CIB"))
		notebook.append_page(cib_vbox, tab_label)

		cib_attrs_vbox = gtk.VBox()
		cib_vbox.pack_start(cib_attrs_vbox)
		self.cib_attrs_vbox = cib_attrs_vbox

		bbox = gtk.HButtonBox()
		bbox.set_layout(gtk.BUTTONBOX_END)
		bbox.set_spacing(5)
		xml_btn = gtk.Button(_("View XML"))
		bbox.add(xml_btn)
		cib_vbox.pack_start(bbox, False)

		xml_menu = gtk.Menu()
		for obj_type in ["cib", "configuration"] :
			if obj_type == "cib" :
				label_text = _("The Whole CIB")
			elif obj_type == "configuration" :
				label_text = _("The Configuration Section")
			xml_menu_item = gtk.MenuItem(label_text)
			xml_menu.append(xml_menu_item)
			xml_menu_item.connect("activate", self.edit_xml, obj_type)

		xml_menu.show_all()
		xml_btn.connect_object("event", self.popup_menu, xml_menu)

		self.update()

	def popup_menu(self, menu, event) :
		if event.type == gtk.gdk.BUTTON_PRESS :
			menu.popup(None, None, None, event.button, event.time)
			return True
		elif event.type == gtk.gdk.KEY_PRESS and event.keyval == gtk.keysyms.Return :
			menu.popup(None, None, None, event.keyval, event.time)
			return True
		return False

	def edit_xml(self, widget, obj_type) :
		init_cib_xml_node = manager.xml_nodes["cib"]

		if obj_type == "cib" :
			xml_node = init_cib_xml_node
		else :
			xml_nodes = init_cib_xml_node.getElementsByTagName(obj_type)
			if len(xml_nodes) < 1 :
				msgbox(top_window, _("The object \"%s\" doesn't exist")%obj_type)
				return
			xml_node = xml_nodes[0]

		orig_xml_node = xml_node.cloneNode(True)
		replace_xml_node = xml_node
		xml_dlg = EditXMLDlg(xml_node)
		while True :
			new_xml_node = xml_dlg.run()
			if new_xml_node == None :
				if obj_type != "cib" :
					replace_xml_node.parentNode.replaceChild(orig_xml_node, replace_xml_node)
				self.update()
				break

			if obj_type == "cib" :
				init_cib_xml_node = new_xml_node
			else :
				replace_xml_node.parentNode.replaceChild(new_xml_node, replace_xml_node)
				replace_xml_node = new_xml_node

			xml_str = new_xml_node.toxml().replace("\n", "")
			if not manager.validate_cib(init_cib_xml_node) :
				continue
			manager.cib_do_cmd("cib_replace\n%s\n%s"%(str(xml_node.tagName), str(xml_str)))
			if manager.failed_reason != "" :
				msgbox(top_window, manager.failed_reason)
			else :
				if obj_type == "cib" :
					manager.set_update()
				else :
					self.update()
				xml_dlg.destroy()
				break

	def save_status(self) :
		page_num = self.notebook.get_current_page()
		if page_num < 0 :
			return None
		else :
			return (page_num,)

	def restore_status(self, view_status) :
		if view_status == None :
			return
		(page_num,) = view_status
		self.notebook.set_current_page(page_num)

class View :
	changed = False
	
	def __init__(self, param=None) :

		bbox = gtk.HButtonBox()
		bbox.set_layout(gtk.BUTTONBOX_END)
		bbox.set_spacing(5)
		default_btn = gtk.Button(_("Default"))
		bbox.add(default_btn)
		reset_btn = gtk.Button(_("Reset"))
		bbox.add(reset_btn)
		apply_btn = gtk.Button(stock=gtk.STOCK_APPLY)
		bbox.add(apply_btn)
		self.bbox = bbox

		self.default_btn_handler = default_btn.connect("clicked", self.on_default)
		self.reset_btn_handler = reset_btn.connect("clicked", self.on_reset)
		self.apply_btn_handler = apply_btn.connect("clicked", self.on_apply)

		self.default_btn = default_btn
		self.reset_btn = reset_btn
		self.apply_btn = apply_btn

		self.widget.pack_start(self.bbox, False, padding = 2)

	def update(self) :
		self.apply_btn.set_property("sensitive", False)
		self.reset_btn.set_property("sensitive", False)
		self.changed = False
	
	def on_changed(self, widget) :
		self.apply_btn.set_property("sensitive", True)
		self.reset_btn.set_property("sensitive", True)
		self.changed = True
	
	def on_reset(self, widget):
		self.update()
		
	def on_apply(self, widget):
		self.apply_btn.set_property("sensitive", False)
		self.reset_btn.set_property("sensitive", False)
		self.changed = False

	def on_default(self, widget):
		self.on_changed(widget)
		
	def on_after_show(self) :
		pass	

class CRMConfigView(View) :
	pengine_metadata = None
	crmd_metadata = None
	pengine_widgetgroup = None
	crmd_widgetgroup = None
	
	def on_apply(self, widget):
		current_page = self.notebook.get_current_page()
		if current_page == 0 :
			(widgetgroup, metadata) = (self.pengine_widgetgroup, self.pengine_metadata)
		else :
			(widgetgroup, metadata) = (self.crmd_widgetgroup, self.crmd_metadata)

		new_crm_config = widgetgroup.get_values()
		self.update_crm_config(metadata, new_crm_config)

		self.update()
		View.on_apply(self, widget)

	def on_default(self, widget):
		current_page = self.notebook.get_current_page()
		if current_page == 0 :
			(widgetgroup, metadata) = (self.pengine_widgetgroup, self.pengine_metadata)
		else :
			(widgetgroup, metadata) = (self.crmd_widgetgroup, self.crmd_metadata)

		default_crm_config = {}
		for parameter in metadata.parameters:
			default_crm_config[parameter["name"]] = str(parameter["content"]["default"])

		if default_crm_config != {}:
			widgetgroup.show_values(default_crm_config)

		View.on_default(self, widget)
	
	def update(self, xml_node = None) :
		for (widgetgroup, metadata) in ((self.pengine_widgetgroup, self.pengine_metadata),
						(self.crmd_widgetgroup, self.crmd_metadata)):
			if metadata != None and widgetgroup != None:
				crm_config = self.get_crm_config(metadata)
				if crm_config != None :
					widgetgroup.show_values(crm_config)
				else :
					return False

		View.update(self)
		self.on_after_show()
		return True

	def get_crm_config(self, metadata) :
		global mode_level
		config = {}
		for parameter in metadata.parameters :
			config[parameter["name"]] = str(parameter["content"]["default"])

		cluster_property_sets = manager.xml_nodes["cib"].getElementsByTagName("cluster_property_set")
		if len(cluster_property_sets) == 0 :
			return config
		elif len(cluster_property_sets) == 1 :
			for nvpair in cluster_property_sets[0].getElementsByTagName("nvpair") :
				name = nvpair.getAttribute("name")
				value = nvpair.getAttribute("value")
				if value != "" :
					config[nvpair.getAttribute("name")] = nvpair.getAttribute("value")
			return config
		else :
			mode_level = 2
			window.radio_tool_action_group.get_action("hack-mode").set_active(True)
			msgbox(top_window, _("Multiple \"Cluster Property Set\" in \"CRM Config\".") + "\n"
					+ _("We are switching to \"Hack Mode\" to view them properly."))
			return None

	def update_crm_config(self, metadata, new_crm_config) :
		crm_config_xml_nodes = manager.xml_nodes["cib"].getElementsByTagName("crm_config")
		if len(crm_config_xml_nodes) < 1 :
			msgbox(top_window, _("Cannot update the crm configuration: No \"crm_config\" in CIB"))
			return

		(parent_xml_node, add_obj_type, new_mid_elem) = \
				manager.real_add_obj_type(crm_config_xml_nodes[0], "cluster_property_set")

		if parent_xml_node == None :
			msgbox(top_window, _("Cannot update the crm configuration"))
			return

		nv_xml_nodes = {}
		for nv_xml_node in parent_xml_node.getElementsByTagName("nvpair") :
			nv_name = nv_xml_node.getAttribute("name")
			nv_xml_nodes[nv_name] = nv_xml_node

		default_crm_config = {}
		for parameter in metadata.parameters :
			default_crm_config[parameter["name"]] = str(parameter["content"]["default"])
			if parameter["content"]["type"] == "integer" :
				try :
					default_value = float(parameter["content"]["default"])
					if default_value == float("inf") :
						default_crm_config[parameter["name"]] = "1000000"
					elif default_value == float("-inf") :
						default_crm_config[parameter["name"]] = "-1000000"
				except :
					pass

		impl = getDOMImplementation()
		for attr_name, value in new_crm_config.iteritems() :
			nv_xml_node = nv_xml_nodes.get(attr_name)

			if nv_xml_node != None :
				if value != default_crm_config.get(attr_name) :
					nv_xml_node.setAttribute("value", value)
				else :
					nv_xml_node.parentNode.removeChild(nv_xml_node)
			else :
				if value != default_crm_config.get(attr_name) :
					newdoc = impl.createDocument(None, "nvpair", None)
					nv = newdoc.documentElement
					parent_xml_node.appendChild(nv)

					attr_id = manager.auto_unique_id(nv, attr_name)
					nv.setAttribute("id", attr_id)
					nv.setAttribute("name", attr_name)
					nv.setAttribute("value", value)

		xml_str = parent_xml_node.toxml().replace("\n", "")
		if new_mid_elem == None :
			manager.cib_do_cmd("cib_replace\ncrm_config\n%s"%(str(xml_str)))
		else :
			manager.cib_do_cmd("cib_create\ncrm_config\n%s"%(str(xml_str)))
			
		if manager.failed_reason != "" :
			msgbox(top_window, manager.failed_reason)

	def on_after_show(self) :
		target_site = "www.clusterlabs.org"
		for widgets in (self.pengine_widgetgroup.widgets, self.crmd_widgetgroup.widgets):
			if widgets != None:
				name_label_max_len = 0
				for key in widgets["name_labels"].keys():
					make_label_active(widgets["name_labels"][key], name_cap(key)+":", target_site)
					name_label_len = widgets["name_labels"][key].size_request()[0]
					if name_label_len >  name_label_max_len :
						name_label_max_len = name_label_len

				for name_label in widgets["name_labels"].values() :
					name_label.set_size_request(name_label_max_len, -1)
							
	def on_notebook_event(self, widget, page, page_num) :
		global last_cluster_view_page_num

		if self.changed == True:
			ret = confirmbox(top_window, _("There are unsaved changes in current page.")+"\n"+_("Apply the changes?"),
					(gtk.STOCK_NO, gtk.RESPONSE_NO, 
					gtk.STOCK_YES, gtk.RESPONSE_YES))
			if ret == gtk.RESPONSE_YES :
				self.on_apply(widget)
			else :
				self.update()

	def __init__(self) :
		vbox = gtk.VBox()
		self.widget = vbox

		notebook = gtk.Notebook()
		self.notebook = notebook
		vbox.pack_start(notebook)

		pe_vbox = gtk.VBox()
		pe_vbox.set_border_width(5)
		tab_label = gtk.Label(_("Policy Engine"))

		sw = gtk.ScrolledWindow()
		sw.set_shadow_type(gtk.SHADOW_NONE)
		sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		sw.add_with_viewport(pe_vbox)
		sw.child.set_shadow_type(gtk.SHADOW_NONE)
		notebook.append_page(sw, tab_label)
		self.pe_vbox = pe_vbox

		crmd_vbox = gtk.VBox()
		crmd_vbox.set_border_width(5)
		tab_label = gtk.Label(_("CRM Daemon"))

		sw = gtk.ScrolledWindow()
		sw.set_shadow_type(gtk.SHADOW_NONE)
		sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		sw.add_with_viewport(crmd_vbox)
		sw.child.set_shadow_type(gtk.SHADOW_NONE)
		notebook.append_page(sw, tab_label)
		self.crmd_vbox = crmd_vbox

		self.pengine_metadata = manager.get_crm_metadata("pengine")
		self.crmd_metadata = manager.get_crm_metadata("crmd")

		if self.pengine_metadata != None:
			pengine_widgets = self.render_crmconf_widgets(self.pengine_metadata)
			self.pengine_widgetgroup = WidgetGroup(pengine_widgets)
		if self.crmd_metadata != None:
			crmd_widgets = self.render_crmconf_widgets(self.crmd_metadata)
			self.crmd_widgetgroup = WidgetGroup(crmd_widgets)

		notebook.connect("switch-page", self.on_notebook_event)

		View.__init__(self)

		self.widget.show_all()
		#self.update()

	def render_crmconf_widgets(self, metadata):
		if metadata.name == "Policy Engine":
			vbox = self.pe_vbox
		elif metadata.name == "CRM Daemon":
			vbox = self.crmd_vbox

		widgets = {}
		name_labels = {}
		combos = {}
		combo_entries = {}
		checkbuttons = {}
		spinbuttons = {}
		entries = {}
		parameters = metadata.parameters

		for row in range(len(parameters)):
			param_name = parameters[row]["name"]
			param_type =  parameters[row]["content"]["type"]
			param_default =  parameters[row]["content"]["default"]

			hbox = gtk.HBox()
			label = gtk.Label(param_name + ":")
			label.set_alignment(0, 0.5)
			eventbox = gtk.EventBox()
			eventbox.add(label)
			hbox.pack_start(eventbox, False, padding=5)
			name_labels[param_name] = label

			longdesc = parameters[row].get("longdesc")
			shortdesc = parameters[row].get("shortdesc")
			if len(longdesc) == 0 :
				tip = shortdesc
			elif longdesc.find(shortdesc) > -1 :
				tip = longdesc
			else :
				if shortdesc.endswith(_(".")) :
					tip = shortdesc + "\n" + longdesc
				else :
					tip = shortdesc + _(".") + "\n" + longdesc

			if param_default != "" :
				default_str =  _("Default") + _(": ") + param_default
				if len(tip) > 0 :
					tip += "\n\n" + default_str
				else :
					tip = default_str 
				

			if pygtk_newer(2, 12) :
                                label.set_tooltip_text(tip)
                        else :
                                tooltips = gtk.Tooltips()
                                tooltips.set_tip(label, tip)

			if param_type == "enum" and parameters[row]["content"].has_key("values"):
				store = gtk.ListStore(str, str)
				for option in parameters[row]["content"]["values"]:
					if param_default != None and option == param_default :
						store.insert(0, [option, "[ "+ _("default") + " ]"])
					else :
						store.append([option, ""])
					
				combo = gtk.ComboBox(store)
				cell0 = gtk.CellRendererText()
				cell1 = gtk.CellRendererText()
				combo.pack_start(cell0, True)
				combo.pack_start(cell1, True)
				combo.add_attribute(cell0, 'text', 0)
				combo.add_attribute(cell1, 'text', 1)

				combo.connect("changed", self.on_changed)
				hbox.pack_start(combo, False, padding=3)
				combos[param_name] = combo
			elif param_type == "boolean":
				checkbutton = gtk.CheckButton()
				checkbutton.connect("toggled", self.on_changed)
				hbox.pack_start(checkbutton, False)
				checkbuttons[param_name] = checkbutton
			elif param_type == "integer" and param_name.count("time") == 0 :
				try :
					default_value = float(param_default)
				except :
					default_value = float(extract_int(param_default))
					if default_value == None :
						default_value = 0

				if default_value == float("inf") :
					default_value = 1000000
				elif default_value == float("-inf") :
					default_value = -1000000

				if param_name.count("node-health") or param_name.count("stickiness") :
					min_value = -1000000
					page_incr = 100
				elif default_value < 0 :
					min_value = default_value
					page_incr = 100
				else :
					min_value = 0
					page_incr = 10
				
				adj = gtk.Adjustment(default_value, min_value, 1000000, 1, page_incr)
				spinbutton = gtk.SpinButton(adj, 0, 0)
				#spinbutton.set_width_chars(7)
				spinbutton.set_wrap(True)

				spinbutton.connect("changed", self.on_changed)
				hbox.pack_start(spinbutton, False, padding=3)
				spinbuttons[param_name] = spinbutton
			elif param_default != "" or  parameters[row]["content"].has_key("values") :
				store = gtk.ListStore(str, str)

				if parameters[row]["content"].has_key("values") :
					for option in parameters[row]["content"]["values"] :
						if param_default != None and option == param_default :
							store.insert(0, [option, "[ "+ _("default") + " ]"])
						else :
							store.append([option, ""])
				else :
					store.insert(0, [param_default, "[ "+ _("default") + " ]"])
					
				combo_entry = gtk.ComboBoxEntry(store)
				cell = gtk.CellRendererText()
				combo_entry.pack_start(cell, True)
				combo_entry.add_attribute(cell, 'text', 1)

				combo_entry.connect("changed", self.on_changed)
				combo_entry.child.connect("activate", self.on_apply)
				hbox.pack_start(combo_entry, False, padding=3)
				combo_entries[param_name] = combo_entry

			else:
				entry = gtk.Entry()
				entry.connect("changed", self.on_changed)
				entry.connect("activate", self.on_apply)
				hbox.pack_start(entry, False, padding=3)
				entries[param_name] = entry 

			vbox.pack_start(hbox, False, padding=1)
	
		vbox.show_all()

		widgets["name_labels"] = name_labels
		widgets["combos"] = combos
		widgets["combo_entries"] = combo_entries
		widgets["checkbuttons"] = checkbuttons
		widgets["spinbuttons"] = spinbuttons
		widgets["entries"] = entries
	
		return widgets

	def save_status(self) :
		page_num = self.notebook.get_current_page()
		if page_num < 0 :
			return None
		else :
			return (page_num,)

	def restore_status(self, view_status) :
		if view_status == None :
			return
		(page_num,) = view_status
		self.notebook.set_current_page(page_num)

class ObjectView :
	obj_attrs = None
	elem_notebook = None
	
	def __init__(self, xml_node, is_newobj = False, change_call_back = None, is_topview = False,
			missing_opt_obj_parent_type = None, show_mode = 0) :
		self.is_newobj = is_newobj
		self.change_call_back = change_call_back
		self.is_topview = is_topview
		self.missing_opt_obj_parent_type = missing_opt_obj_parent_type
		self.show_mode = show_mode
		vbox = gtk.VBox()
		self.vbox = vbox
		self.widget = vbox

		self.mode_combobox = gtk.combo_box_new_text()
		self.mode_combobox.append_text(_("List Mode"))
		self.mode_combobox.append_text(_("Tree Mode"))
		self.mode_combobox.append_text(_("XML Mode"))
		self.mode_combobox.set_active(self.show_mode)
		self.mode_combobox.connect("changed", self.on_changed)

		self.hbox = gtk.HBox()
		self.hbox.pack_end(self.mode_combobox, False)

		self.label = gtk.Label(_("Show") + _(": "))
		self.hbox.pack_end(self.label, False)

		self.vbox.pack_start(self.hbox, False, padding=2)

		self.update(xml_node)

	def update(self, xml_node = None) :
		is_newobj = self.is_newobj
		if type(xml_node) == str:
			impl = getDOMImplementation()
			newdoc = impl.createDocument(None, xml_node, None)
			self.xml_node = newdoc.documentElement
			self.init_xml_node = self.xml_node.cloneNode(True)
			self.is_fake_xml_node = True
		elif xml_node != None :
			self.xml_node = xml_node
			self.init_xml_node = self.xml_node.cloneNode(True)
			self.is_fake_xml_node = False

		objview_status = self.save_status()

		for child in self.vbox.get_children() :
			if child != self.hbox :
				self.vbox.remove(child)

		obj_type = self.xml_node.tagName
		attr_is_any_name = False
		elem_is_any_name = False
		if validate_type == "dtd" :
			self.dtd_elem = manager.get_dtd_elem(obj_type)
			attr_list = self.dtd_elem.get_attr_list()
			sub_obj_list = self.dtd_elem.get_content_model()[1]
		else :
			sorted_rng_nodes = manager.sorted_sub_rng_nodes_by_name(obj_type)
			attr_list = []
			sub_obj_list = []
			if sorted_rng_nodes != None :
				attr_rng_nodes = sorted_rng_nodes.get("attribute", [])
				elem_rng_nodes = sorted_rng_nodes.get("element", [])
				for rng_node in attr_rng_nodes :
					name = rng_node[0][1].getAttribute("name")
					if name == "" :
						attr_is_any_name = True
					elif attr_list.count(name) == 0 :
						attr_list.append(name)

				for rng_node in elem_rng_nodes :
					name = rng_node[0][1].getAttribute("name")
					if name == "" :
						elem_is_any_name = True
					else :
						sub_obj_list.append(name)
			else :
				attr_is_any_name = True
				elem_is_any_name = True

		if attr_is_any_name :
			for attr_name in  self.xml_node.attributes.keys() :
				if attr_list.count(attr_name) == 0 :
					attr_list.append(attr_name)

		if elem_is_any_name :
			for elem_node in self.xml_node.childNodes :
				if elem_node.nodeType != xml.dom.Node.ELEMENT_NODE :
					continue
				elem_name = elem_node.tagName
				if sub_obj_list.count(elem_name) == 0 :
					sub_obj_list.append(elem_name)

		if not self.is_topview and (len(attr_list) >0 or attr_is_any_name) :
			has_attr = True
		else :
			has_attr = False

		if len(sub_obj_list) or elem_is_any_name > 0 :
			has_elem = True
		else :
			has_elem = False

		if len(attr_list) > 4 :
			obj_box = gtk.HBox()
			self.vbox.pack_start(obj_box)
		else :
			obj_box = self.vbox

		if has_attr :
			if obj_type in ["primitive", "template"] :
				obj_attrs = Primitive(self.xml_node, is_newobj, self.change_call_back)
			elif obj_type == "rsc_order" :
				obj_attrs = RscOrder(self.xml_node, is_newobj, self.change_call_back)
			elif obj_type == "rsc_colocation" :
				obj_attrs = RscColocation(self.xml_node, is_newobj, self.change_call_back)
			elif obj_type == "nvpair" :
				if validate_type == "dtd" :
					if self.xml_node.parentNode.parentNode.tagName == "instance_attributes" and \
							self.xml_node.parentNode.parentNode.parentNode.tagName in ["primitive", "template"] :
						obj_attrs = PrimInstAttrsNV(self.xml_node, is_newobj, self.change_call_back)
					elif self.xml_node.parentNode.parentNode.tagName == "instance_attributes" and \
							self.xml_node.parentNode.parentNode.parentNode.tagName == "op" :
						obj_attrs = OPInstAttrsNV(self.xml_node, is_newobj, self.change_call_back)
					elif self.xml_node.parentNode.parentNode.tagName == "instance_attributes" and \
							self.xml_node.parentNode.parentNode.parentNode.tagName == "node" :
						obj_attrs = InstAttrsNV(self.xml_node, is_newobj, self.change_call_back)
					elif self.xml_node.parentNode.parentNode.tagName == "meta_attributes" :
						obj_attrs = MetaAttrsNV(self.xml_node, is_newobj, self.change_call_back)
					elif self.xml_node.parentNode.parentNode.tagName == "cluster_property_set" :
						obj_attrs = CRMConfNV(self.xml_node, is_newobj, self.change_call_back)
					elif self.xml_node.parentNode.parentNode.tagName == "utilization" :
                                                obj_attrs = UtilizationNV(self.xml_node, is_newobj, self.change_call_back)
					else :
						obj_attrs = ObjectAttrs(self.xml_node, is_newobj, self.change_call_back)
				else :
					if self.xml_node.parentNode.tagName == "instance_attributes" and \
							self.xml_node.parentNode.parentNode.tagName in ["primitive", "template"] :
						obj_attrs = PrimInstAttrsNV(self.xml_node, is_newobj, self.change_call_back)
					elif self.xml_node.parentNode.tagName == "instance_attributes" and \
							self.xml_node.parentNode.parentNode.tagName == "op" :
						obj_attrs = OPInstAttrsNV(self.xml_node, is_newobj, self.change_call_back)
					elif self.xml_node.parentNode.tagName == "instance_attributes" and \
							self.xml_node.parentNode.parentNode.tagName == "node" :
						obj_attrs = InstAttrsNV(self.xml_node, is_newobj, self.change_call_back)
					elif self.xml_node.parentNode.tagName == "meta_attributes" :
						if self.xml_node.parentNode.parentNode.tagName == "op_defaults" :
							obj_attrs = OPDefaultsNV(self.xml_node, is_newobj, self.change_call_back)
						else :
							obj_attrs = MetaAttrsNV(self.xml_node, is_newobj, self.change_call_back)
					elif self.xml_node.parentNode.tagName == "cluster_property_set" :
						obj_attrs = CRMConfNV(self.xml_node, is_newobj, self.change_call_back)
					elif self.xml_node.parentNode.tagName == "utilization" :
                                                obj_attrs = UtilizationNV(self.xml_node, is_newobj, self.change_call_back)
					else :
						obj_attrs = ObjectAttrs(self.xml_node, is_newobj, self.change_call_back)

			elif obj_type == "expression" :
				obj_attrs = Expression(self.xml_node, is_newobj, self.change_call_back)
			elif obj_type == "op" :
				obj_attrs = OP(self.xml_node, is_newobj, self.change_call_back)
			else :
				obj_attrs = ObjectAttrs(self.xml_node, is_newobj, self.change_call_back)

			obj_attrs.dynamic_choice_elem()
			obj_attrs.update()

			obj_box.pack_start(obj_attrs.attrs_vbox)
			self.obj_attrs = obj_attrs
			
		if has_elem :
                        if obj_type in ["acl_user", "acl_role"] :
                                single_page = True
                        else :
                                single_page = False

			self.elem_notebook = ElementNotebook(self.xml_node, self.is_topview, self.elem_change_call_back,
						self.show_mode, self.is_fake_xml_node, self.missing_opt_obj_parent_type, single_page)
			if self.elem_notebook.update(self.xml_node) :
				obj_box.pack_start(self.elem_notebook.widget, True, padding = 5)
				self.vbox.pack_start(self.elem_notebook.bbox, False, padding = 2)
			else :
				#if not self.is_topview :
				#	self.update()
				self.update()
				return

		self.restore_status(objview_status)

		self.vbox.show_all()
		self.on_after_show()

		if not has_elem :
			self.label.hide_all()
			self.mode_combobox.hide_all()

	def elem_change_call_back(self) :
		if self.obj_attrs != None :
			self.obj_attrs.dynamic_choice_elem()

		if self.change_call_back != None :
			self.change_call_back()

	def save_status(self) :
		attrs_status = None
		if self.obj_attrs != None :
			attrs_status = self.obj_attrs.save_status()

		notebook_status = None
		if self.elem_notebook != None :
			notebook_status = self.elem_notebook.save_status()
		return (self.show_mode, attrs_status, notebook_status)

	def restore_status(self, objview_status) :
		#if objview_status == None :
		#	return
		(show_mode, attrs_status, notebook_status) = objview_status
		if self.obj_attrs != None and attrs_status != None :
			self.obj_attrs.restore_status(attrs_status)
		if self.elem_notebook != None and notebook_status != None :
			self.elem_notebook.restore_status(notebook_status)

	def on_after_show(self) :
		if self.obj_attrs != None :
			self.obj_attrs.on_after_show()
		if self.elem_notebook != None :
			self.elem_notebook.on_after_show()

	def on_changed(self, widget) :
		show_mode = self.mode_combobox.get_active()
		if show_mode != 2 :
			self.show_mode = show_mode
			self.update()
			return

		self.edit_xml()
		self.mode_combobox.set_active(self.show_mode)

	def edit_xml(self) :
		init_cib_xml_node = manager.xml_nodes["cib"]
		orig_xml_node = self.xml_node.cloneNode(True)
		replace_xml_node = self.xml_node
		xml_dlg = EditXMLDlg(self.xml_node)
		while True :
			new_xml_node = xml_dlg.run()
			if new_xml_node == None :
				replace_xml_node.parentNode.replaceChild(orig_xml_node, replace_xml_node)
				self.xml_node = orig_xml_node
				self.update()
				break
			replace_xml_node.parentNode.replaceChild(new_xml_node, replace_xml_node)
			replace_xml_node = new_xml_node
			if not self.is_topview :
				xml_dlg.destroy()
				#self.xml_node.parentNode.replaceChild(new_xml_node, self.xml_node)
				self.xml_node = new_xml_node
				self.update()
				if self.change_call_back != None :
					self.change_call_back()
				break
			else :
				xml_str = new_xml_node.toxml().replace("\n", "")
				if self.is_fake_xml_node :
					manager.cib_do_cmd("cib_create\n%s\n%s"
							%(str(self.missing_opt_obj_parent_type), str(xml_str)))
					if manager.failed_reason != "" :
						msgbox(top_window, manager.failed_reason)
					else :
						if manager.active_cib != "" :
							manager.set_update()
						xml_dlg.destroy()
						break
				else :
					if not manager.validate_cib(init_cib_xml_node) :
						continue
					manager.cib_do_cmd("cib_replace\n%s\n%s"%(str(self.xml_node.tagName), str(xml_str)))
					if manager.failed_reason != "" :
						msgbox(top_window, manager.failed_reason)
					else :
						#self.xml_node.parentNode.replaceChild(new_xml_node, self.xml_node)
						self.xml_node = new_xml_node
						self.update()
						xml_dlg.destroy()
						break

	def validate(self) :
		passed = True
		if self.obj_attrs != None :
			passed = self.obj_attrs.verify_values()
		return passed

	def reset(self) :
		new_xml_node = self.init_xml_node.cloneNode(True)
		try :
			self.xml_node.parentNode.replaceChild(new_xml_node, self.xml_node)
		except xml.dom.NotFoundErr :
			msgbox(top_window, _("The object doesn't exist"))
			return
		self.xml_node = new_xml_node

class EditXMLDlg:
	def __init__(self, xml_node) :
		global top_window
		self.xml_node = xml_node

		dialog = gtk.Dialog(_("Edit XML"), top_window, gtk.DIALOG_MODAL,
			(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, str(_("Reset")), gtk.RESPONSE_APPLY, gtk.STOCK_OK, gtk.RESPONSE_OK))
		dialog.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_NORMAL)
		dialog.set_default_size(750, 550)

		ui_xml = '''
		<ui>
			<toolbar name="toolbar">
				<toolitem action="import"/>
				<toolitem action="export"/>
			</toolbar>
			
		</ui>'''

		actions = [
			("import", gtk.STOCK_REVERT_TO_SAVED, _("Import"), "<Ctrl>o",
				_("Import XML"), self.import_xml),
			("export", gtk.STOCK_SAVE_AS, _("Export"), "<Ctrl>s",
				_("Export XML"), self.export_xml)
			 ]

		action_group = gtk.ActionGroup("rw_xml_file")
		action_group.add_actions(actions)

		uimanager = gtk.UIManager()
		uimanager.insert_action_group(action_group, 0)
		uimanager.add_ui_from_string(ui_xml)

		#toolbar = gtk.Toolbar()
		#toolbar.set_orientation(gtk.ORIENTATION_HORIZONTAL)
		#toolbar.set_style(gtk.TOOLBAR_BOTH)

		toolbar = uimanager.get_widget('/toolbar')
		toolbar.set_style(gtk.TOOLBAR_BOTH)
		dialog.vbox.pack_start(toolbar, False)

		#tool_item = action_group.get_action("import").create_tool_item()
		#toolbar.insert(tool_item, -1)

		#tool_item = action_group.get_action("export").create_tool_item()
		#toolbar.insert(tool_item, -1)

		sw = gtk.ScrolledWindow()
		sw.set_shadow_type(gtk.SHADOW_IN)
		sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		self.xml_text = gtk.TextView()
		self.xml_text.set_wrap_mode(gtk.WRAP_WORD)
		self.xml_textbuffer = self.xml_text.get_buffer()
		sw.add(self.xml_text)
		dialog.vbox.pack_start(sw, padding=1)
		dialog.set_response_sensitive(gtk.RESPONSE_APPLY, False)

		self.statusbar = gtk.Statusbar()
		dialog.vbox.pack_end(self.statusbar, False)

		self.xml_str = xml_node.toxml()
		self.xml_textbuffer.set_text(self.xml_str)
		self.update_statusbar()
		self.xml_textbuffer.connect("changed", self.on_changed)

		self.xml_text.connect_after("move-cursor", self.update_statusbar)
		self.xml_text.connect("event-after", self.on_click_text)
		self.xml_text.connect_after("toggle-overwrite", self.update_statusbar)
		dialog.show_all()
		self.dialog = dialog
		self.save_top_window = top_window
		top_window = dialog

	def on_changed(self, widget) :
		self.dialog.set_response_sensitive(gtk.RESPONSE_APPLY, True)
		self.update_statusbar()

	def on_click_text(self, widget, event) :
		if event.type == gtk.gdk.BUTTON_PRESS and event.button == 1 :
			self.update_statusbar()

	def update_statusbar(self, textview = None , step_size = None, count = None, extend_selection = None) :
		iter = self.xml_textbuffer.get_iter_at_mark(self.xml_textbuffer.get_insert())
		line = iter.get_line()
		column = iter.get_line_offset()

		if self.xml_text.get_overwrite() :
			overwrite = _("OVR")
		else :
			overwrite = _("INS")

		self.statusbar.pop(0)
		self.statusbar.push(0, _("Ln %d, Col %d\t%s")%(line+1, column+1, overwrite))

	def run(self) :
		while True :
			ret = self.dialog.run()
			if ret in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT] :
				self.destroy()
				return None
			elif ret == gtk.RESPONSE_APPLY :
				self.xml_textbuffer.set_text(self.xml_str)
				self.dialog.set_response_sensitive(gtk.RESPONSE_APPLY, False)
			else :
				new_xml_str = self.xml_textbuffer.get_text(*self.xml_textbuffer.get_bounds())
				try :
					new_xml_node = parseString(new_xml_str).documentElement
				except xml.parsers.expat.ExpatError, msg :
					msgbox(top_window, _("Failed to parse the XML") + _(": ") + str(msg))
					continue

				return new_xml_node

	def destroy(self) :
		global top_window
		self.dialog.destroy()
		top_window = self.save_top_window

	def import_xml(self, widget) :
		global top_window
		file_dialog = gtk.FileChooserDialog(_("Open File"), None, 
				gtk.FILE_CHOOSER_ACTION_OPEN,
				(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
				gtk.STOCK_OPEN, gtk.RESPONSE_OK))

		save_top_window = top_window
		top_window = file_dialog

		filter = gtk.FileFilter()
		filter.set_name(_("All files"))
		filter.add_pattern("*")
		file_dialog.add_filter(filter)

		filter = gtk.FileFilter()
		filter.set_name(_("XML files"))
		filter.add_pattern("*.xml")
		file_dialog.add_filter(filter)

		ret = file_dialog.run()
		if ret in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT] :
			open_file = None
		else :
			open_file = file_dialog.get_filename()

		top_window = save_top_window
		file_dialog.destroy()

		if open_file == None :
			return

		try :
			file_obj = open(open_file)
		except IOError, msg :
			msgbox(top_window, _("I/O error") + _(": ") + str(msg))
			return
		
		try :
			new_xml_str = file_obj.read()
		except IOError, msg :
			msgbox(top_window, _("I/O error") + _(": ") + str(msg))
			file_obj.close()
			return
		file_obj.close()

		self.xml_textbuffer.set_text(new_xml_str)

	def export_xml(self, widget) :
		sfdlg = SelectFileDlg()
		node_id = self.xml_node.getAttribute("id")
		if node_id == "" :
			default_name = self.xml_node.tagName +  ".xml"
		else :
			default_name = self.xml_node.tagName + "-" + self.xml_node.getAttribute("id") + ".xml"
		(save_file, save_type) = sfdlg.select_file(default_name)
		if save_file == None :
			return

		try :
			fd = os.open(save_file, os.O_RDWR|os.O_CREAT|os.O_TRUNC, 0644)
		except OSError, msg :
			msgbox(top_window, _("System error") + _(": ") + str(msg))
			return

		new_xml_str = self.xml_textbuffer.get_text(*self.xml_textbuffer.get_bounds())

		try :
			os.write(fd, new_xml_str)
		except OSError, msg :
			msgbox(top_window, _("System error") + _(": ") + str(msg))
			os.close(fd)
			return
		os.close(fd)

class ElementNotebook :
	notebook = None
	new_page_type = None
	def __init__(self, xml_node, is_topview = False, change_call_back = None, show_mode = 0,
				is_fake_xml_node = False, missing_opt_obj_parent_type = None, single_page = False) :
		self.is_topview = is_topview
		self.change_call_back = change_call_back
		self.show_mode = show_mode
		self.is_fake_xml_node = is_fake_xml_node
		self.missing_opt_obj_parent_type = missing_opt_obj_parent_type
		self.single_page = single_page
		vbox = gtk.VBox()
		self.widget = vbox

		self.hbox = gtk.HBox()
		vbox.pack_start(self.hbox)

		self.sub_vbox = gtk.VBox()
		vbox.pack_start(self.sub_vbox, False)

		bbox = gtk.HButtonBox()
		bbox.set_layout(gtk.BUTTONBOX_END)
		bbox.set_spacing(5)
		add_btn = gtk.Button(stock=gtk.STOCK_ADD)
		bbox.add(add_btn)
		edit_btn = gtk.Button(stock=gtk.STOCK_EDIT)
		bbox.add(edit_btn)
		del_btn = gtk.Button(stock=gtk.STOCK_REMOVE)
		bbox.add(del_btn)
		self.bbox = bbox

		self.add_btn_handler = add_btn.connect("clicked", self.on_add)
		self.edit_btn_handler = edit_btn.connect("clicked", self.on_edit)
		self.del_btn_handler = del_btn.connect("clicked", self.on_del)

		self.add_btn = add_btn
		self.edit_btn = edit_btn
		self.del_btn = del_btn

	def update(self, xml_node = None) :
		global mode_level
		if xml_node != None :
			self.xml_node = xml_node
		self.elem_lists = []
		self.pages = []
		self.obj_type = self.xml_node.tagName
		for child in self.hbox.get_children() :
			self.hbox.remove(child)

		self.notebook = gtk.Notebook()
		self.hbox.pack_start(self.notebook, True, padding=2)

		if validate_type == "dtd" :
			self.dtd_elem = manager.get_dtd_elem(self.obj_type)
                        names = [name for (name, mod) in self.dtd_elem.get_content_model()[1]]
                        if self.single_page :
                                elem_node_list = []
                                for elem_node in self.xml_node.childNodes :
                                        if elem_node.nodeType != xml.dom.Node.ELEMENT_NODE :
                                                continue
                                        elem_node_list.append(elem_node)

                                self.pages.append(None)

                                if self.show_mode == 0 :
                                        elem_list = ElementList(names, elem_node_list)
                                else :
                                        elem_list = ElementTree(names, elem_node_list)
                                self.notebook.append_page(elem_list.widget)
                                self.notebook.set_show_tabs(False)
                                self.elem_lists.append(elem_list)
                                elem_list.tree.connect("cursor-changed", self.on_cursor_changed)
                                elem_list.tree.connect("event-after", self.on_click)
                        else :
                            for name in names :
				elem_node_list = []
				for elem_node in self.xml_node.getElementsByTagName(name) :
					if elem_node in self.xml_node.childNodes :
						elem_node_list.append(elem_node)

				if len(elem_node_list) == 0 :
					if self.is_topview :
						continue
					elif mode_level != 0 :
						continue
					elif name in ["resource_set", "rule", "lifetime", "expression", "date_expression", "duration", "date_spec"] \
							or (self.obj_type in ["group"]
								and name in ["instance_attributes"]) \
							or (self.obj_type in ["clone", "master"]
								and name in ["primitive", "group", "instance_attributes"]) \
							or (self.obj_type in ["op"] 
								and name in ["meta_attributes", "instance_attributes"]) :
						continue

				#if len(elem_node_list) > 0 :
				if True :
					self.pages.append(name)
					tab_label = gtk.Label(_(name_cap(name)))
					sub_dtd_elem = manager.get_dtd_elem(name)
					if len(sub_dtd_elem.get_attr_list()) == 0 \
							or (mode_level != 2 and name in
							["meta_attributes", "instance_attributes", "operations",
							"cluster_property_set", "utilization"]) :
						if len(elem_node_list) > 1 and len(sub_dtd_elem.get_attr_list()) > 0 :
							mode_level = 2
							window.radio_tool_action_group.get_action("hack-mode").set_active(True)
							#if not self.is_topview :
							if True :
								msgbox(top_window, _("The \"%s\" has multiple \"%s\" sets.")
									%(_(name_cap(self.obj_type)), _(name_cap(name))) + "\n"
									+ _("We are switching to \"Hack Mode\" to view them properly."))
							return False

						if len(sub_dtd_elem.get_attr_list()) == 0 :
							(name, mod) = sub_dtd_elem.get_content_model()[1][0]
						else :
							(name, mod) = sub_dtd_elem.get_content_model()[1][1]
						sub_elem_node_list = []
						for elem_node in elem_node_list :
							for sub_elem_node in elem_node.childNodes :
								if sub_elem_node.nodeType != xml.dom.Node.ELEMENT_NODE :
									continue
								if sub_elem_node.tagName == name :
									sub_elem_node_list.append(sub_elem_node)
								else :
									mode_level = 2
									window.radio_tool_action_group.get_action("hack-mode").set_active(True)
									#if not self.is_topview :
									if True :
										msgbox(top_window, _("The \"%s\" has a \"%s\".")
											%(_(name_cap(elem_node.tagName)),
											name_cap(sub_elem_node.tagName)) + "\n"
											+ _("We are switching to \"Hack Mode\" to view them properly."))
									return False

						if len(sub_dtd_elem.get_attr_list()) == 0 :
							elem_node_list = sub_elem_node_list
						else :
							sub_sub_dtd_elem = manager.get_dtd_elem(name)
							(name, mod) = sub_sub_dtd_elem.get_content_model()[1][0]

							sub_sub_elem_node_list = []
							for sub_elem_node in sub_elem_node_list :
								for sub_sub_elem_node in sub_elem_node.getElementsByTagName(name) :
									if sub_sub_elem_node in sub_elem_node.childNodes :
										sub_sub_elem_node_list.append(sub_sub_elem_node)
							elem_node_list = sub_sub_elem_node_list

					if self.show_mode == 0 :
						elem_list = ElementList([name], elem_node_list)
					else :
						elem_list = ElementTree([name], elem_node_list)
					self.notebook.append_page(elem_list.widget, tab_label)
					self.elem_lists.append(elem_list)
					elem_list.tree.connect("cursor-changed", self.on_cursor_changed)
					elem_list.tree.connect("event-after", self.on_click)
		else :
			elem_node_dict = {}
			for elem_node in self.xml_node.childNodes :
				if elem_node.nodeType != xml.dom.Node.ELEMENT_NODE :
					continue
				name = elem_node.tagName
				if elem_node_dict.get(name) == None :
					elem_node_dict[name] = []
				elem_node_dict[name].append(elem_node)

			sorted_rng_nodes = manager.sorted_sub_rng_nodes_by_name(self.obj_type)
			self.elem_rng_node_dict = {}
			self.attr_rng_node_dict = {}
			is_any_name = False
			elem_type_list = []
			if sorted_rng_nodes != None :
				self.elem_rng_nodes = sorted_rng_nodes.get("element", [])
				attr_rng_nodes = sorted_rng_nodes.get("attribute", [])
				for rng_node in self.elem_rng_nodes :
					name = rng_node[0][1].getAttribute("name")
					if name == "" :
						is_any_name = True
					else :
						if elem_type_list.count(name) == 0 :
							elem_type_list.append(name)
							self.elem_rng_node_dict[name] = []
						self.elem_rng_node_dict[name].append(rng_node)

				for rng_node in attr_rng_nodes :
					name = rng_node[0][1].getAttribute("name")
					if not self.attr_rng_node_dict.has_key(name) :
						self.attr_rng_node_dict[name] = []
					self.attr_rng_node_dict[name].append(rng_node)
			else :
				self.elem_rng_nodes = []
				is_any_name = True

			self.is_any_name = is_any_name
			other_elem_types = []
			if is_any_name :
				for name in elem_node_dict.keys() :
					if elem_type_list.count(name) == 0 :
						other_elem_types.append(name)
				
                        if self.single_page :
                                names = []
                                for rng_node in self.elem_rng_nodes :
                                        name = rng_node[0][1].getAttribute("name")
                                        if names.count(name) == 0 :
                                                names.append(name)
 
                                elem_node_list = []
                                for elem_node in self.xml_node.childNodes :
                                        if elem_node.nodeType != xml.dom.Node.ELEMENT_NODE :
                                                continue
                                        elem_node_list.append(elem_node)
 
                                self.pages.append(None)

                                if self.show_mode == 0 :
                                        elem_list = ElementList(names, elem_node_list)
                                else :
                                        elem_list = ElementTree(names, elem_node_list)
                                self.notebook.append_page(elem_list.widget)
                                self.notebook.set_show_tabs(False)
                                self.elem_lists.append(elem_list)
                                elem_list.tree.connect("cursor-changed", self.on_cursor_changed)
                                elem_list.tree.connect("event-after", self.on_click)
                        else :
                            for rng_node in self.elem_rng_nodes :
				name = rng_node[0][1].getAttribute("name")
				elem_node_list = elem_node_dict.get(name, [])
				if len(elem_node_list) == 0 :
					if self.is_topview :
						continue
					elif mode_level != 0 :
						continue
					elif name in ["resource_set", "rule", "lifetime", "expression", "date_expression", "duration", "date_spec"] \
							or (self.obj_type in ["group"]
								and name in ["instance_attributes"]) \
							or (self.obj_type in ["clone", "master"] 
								and name in ["primitive", "group", "instance_attributes"]) \
							or (self.obj_type in ["op"] 
								and name in ["meta_attributes", "instance_attributes"]) :
						continue

				self.pages.append(name)
				tab_label = gtk.Label(_(name_cap(name)))
				sub_rng_nodes = manager.sorted_sub_rng_nodes_by_node(*rng_node[0])
				if sub_rng_nodes != None :
					sub_attr_rng_nodes = sub_rng_nodes.get("attribute", [])
					sub_elem_rng_nodes = sub_rng_nodes.get("element", [])

					if len(sub_attr_rng_nodes) == 0 \
							or (mode_level != 2 and name in 
							["meta_attributes", "instance_attributes", "operations",
							"cluster_property_set", "utilization"]) :
						if len(elem_node_list) > 1 and len(sub_attr_rng_nodes) > 0 :
							mode_level = 2
							window.radio_tool_action_group.get_action("hack-mode").set_active(True)
							#if not self.is_topview :
							if True :
								msgbox(top_window, _("The \"%s\" has multiple \"%s\" sets.")
									%(_(name_cap(self.obj_type)), _(name_cap(name))) + "\n"
									+ _("We are switching to \"Hack Mode\" to view them properly."))
							return False
						sub_elem_node_list = []
						for sub_elem_rng_node in sub_elem_rng_nodes :
							if manager.find_decl(sub_elem_rng_node, "optional") != 0 :
								continue
							name = sub_elem_rng_node[0][1].getAttribute("name")
							for elem_node in elem_node_list :
								for sub_elem_node in elem_node.childNodes :
									if sub_elem_node.nodeType != xml.dom.Node.ELEMENT_NODE :
										continue
									if sub_elem_node.tagName == name :
										sub_elem_node_list.append(sub_elem_node)
									else :
										mode_level = 2
										window.radio_tool_action_group.get_action("hack-mode").set_active(True)
										#if not self.is_topview :
										if True :
											msgbox(top_window, _("The \"%s\" has a \"%s\".")
												%(_(name_cap(elem_node.tagName)),
												name_cap(sub_elem_node.tagName)) + "\n"
												+ _("We are switching to \"Hack Mode\" to view them properly."))
										return False

							elem_node_list = sub_elem_node_list
							break
				if self.show_mode == 0 :
					elem_list = ElementList([name], elem_node_list)
				else :
					elem_list = ElementTree([name], elem_node_list)
				self.notebook.append_page(elem_list.widget, tab_label)
				self.elem_lists.append(elem_list)
				elem_list.tree.connect("cursor-changed", self.on_cursor_changed)
				elem_list.tree.connect("event-after", self.on_click)

			for name in other_elem_types :
				elem_node_list = elem_node_dict.get(name, [])
				if len(elem_node_list) == 0 :
					continue

				self.pages.append(name)
				tab_label = gtk.Label(_(name_cap(name)))
				
				sub_attr_list = []
				for elem_node in elem_node_list :
					for attr_name in elem_node.attributes.keys() :
						if sub_attr_list.count(attr_name) == 0 :
							sub_attr_list.append(attr_name)
				if len(sub_attr_list) == 0 :
					sub_elem_node_list = []
					for elem_node in elem_node_list :
						for sub_elem_node in elem_node.childNodes :
							if sub_elem_node.nodeType != xml.dom.Node.ELEMENT_NODE :
								continue
							name = sub_elem_node.tagName
							sub_elem_node_list.append(sub_elem_node)
					elem_node_list = sub_elem_node_list

				if self.show_mode == 0 :
					elem_list = ElementList([name], elem_node_list)
				else :
					elem_list = ElementTree([name], elem_node_list)
				self.notebook.append_page(elem_list.widget, tab_label)
				self.elem_lists.append(elem_list)
				elem_list.tree.connect("cursor-changed", self.on_cursor_changed)
				elem_list.tree.connect("event-after", self.on_click)

		if self.notebook.get_n_pages() > 0 :
			bbox = gtk.VButtonBox()
			bbox.set_layout(gtk.BUTTONBOX_SPREAD)
			bbox.set_spacing(5)
			up_btn = gtk.Button(stock=gtk.STOCK_GO_UP)
			bbox.add(up_btn)
			down_btn = gtk.Button(stock=gtk.STOCK_GO_DOWN)
			bbox.add(down_btn)
			self.hbox.pack_start(bbox, False, padding=2)

			self.up_btn = up_btn
			self.down_btn = down_btn

			up_btn.connect("clicked", self.on_up)
			down_btn.connect("clicked", self.on_down)

			self.hbox.show_all()
			self.notebook.set_size_request(350, 180)
                        self.notebook.set_scrollable(True)
                        self.notebook.popup_enable()
			self.notebook.connect("switch-page", self.on_switch_page)
		else:
			for child in self.sub_vbox.get_children() :
				self.sub_vbox.remove(child)

		return True

	def on_after_show(self, page_num = None) :
		selected_node = self.get_selected_node(page_num)

		self.edit_btn.set_sensitive(selected_node != None)
		self.del_btn.set_sensitive(selected_node != None)

		elem_list = self.get_elem_list(page_num)
		if elem_list == None or selected_node == None :
			self.show_sub_attrs(None)
			return

		(model, iter) = elem_list.tree.get_selection().get_selected()

		self.up_btn.set_sensitive(iter != None and model.get_path(iter)[-1] != 0)
		self.down_btn.set_sensitive(iter != None and model.iter_next(iter) != None)
		self.show_sub_attrs(selected_node)

	def show_sub_attrs(self, selected_node) :
		for child in self.sub_vbox.get_children() :
			self.sub_vbox.remove(child)

		if selected_node == None :
			return

		if validate_type == "dtd" :
			dtd_elem = manager.get_dtd_elem(selected_node.tagName)
			attr_list = dtd_elem.get_attr_list()
		else :
			attr_list = []
			is_any_name = False
			sorted_rng_nodes = manager.sorted_sub_rng_nodes_by_name(selected_node.tagName)
			if sorted_rng_nodes != None :
				attr_rng_nodes = sorted_rng_nodes.get("attribute", [])
				for rng_node in attr_rng_nodes :
					name = rng_node[0][1].getAttribute("name")
					if name == "" :
						is_any_name = True
					elif attr_list.count(name) == 0 :
						attr_list.append(name)
			else :
				is_any_name = True

			if is_any_name :
				for attr_name in  selected_node.attributes.keys() :
					if attr_list.count(attr_name) == 0 :
						if attr_name == "id" :
							attr_list.insert(0, attr_name)
						else :
							attr_list.append(attr_name)

		name_labels = {}
		name_label_max_len = 0
		for attr_name in attr_list :
			attr_value = selected_node.getAttribute(attr_name)
			if attr_value == "" or name_labels.get(attr_name) != None :
				continue
			hbox = gtk.HBox()
			name_label = gtk.Label(_(name_cap(attr_name)+":"))
			name_label.set_alignment(0, 0.5)
			name_label.set_selectable(True)

			name_labels[attr_name] = name_label
			name_label_len = name_label.size_request()[0]
			if name_label_len > name_label_max_len :
				name_label_max_len = name_label_len

			value_label = gtk.Label(attr_value)
			value_label.set_alignment(0, 0.5)
			value_label.set_selectable(True)

			hbox.pack_start(name_label, False, padding=5)
			hbox.pack_start(value_label, False, padding=5)
			self.sub_vbox.pack_start(hbox, False, padding=2)

		for name_label in name_labels.values() :
			name_label.set_size_request(name_label_max_len + 20, -1)

		self.sub_vbox.show_all()

	def on_cursor_changed(self, treeview) : 
		self.on_after_show()

	def on_click(self, widget, event) :
		if (event.type == gtk.gdk._2BUTTON_PRESS and event.button == 1) \
			or ( event.type == gtk.gdk.KEY_PRESS and event.keyval == gtk.keysyms.Return) :
			self.on_edit(widget)

	def on_switch_page(self, notebook, page, page_num) :
		self.on_after_show(page_num)

	def get_selected_node(self, page_num = None) :
		if page_num == None :
			page_num = self.notebook.get_current_page()
		if page_num >= 0 :
			selected_node = self.elem_lists[page_num].get_selected_node()
		else :
			selected_node = None
		return selected_node

	def get_elem_list(self, page_num = None) :
		if page_num == None :
			page_num = self.notebook.get_current_page()
		if page_num >= 0 :
			elem_list = self.elem_lists[page_num]
		else :
			elem_list = None
		return elem_list

	def on_add(self, widget = None, invoked_by_wizard = False, append_title = "") :
		global top_window
		init_cib_xml_node = manager.xml_nodes["cib"]

		elem_rng_nodes = []
		if validate_type == "dtd" :
			option_list = self.get_elem_options_dtd()
		else :
			option_list = []
			elem_is_any_name = False
			elem_rng_nodes = self.get_elem_options_rng()
			if elem_rng_nodes == [] :
				elem_is_any_name = self.is_any_name
			for rng_node in elem_rng_nodes :
				name = rng_node[0][1].getAttribute("name")
				if name == "" :
					elem_is_any_name = True
				else :
					option_list.append(rng_node)

			if elem_is_any_name :
				for elem_node in self.xml_node.childNodes :
					if elem_node.nodeType != xml.dom.Node.ELEMENT_NODE :
						continue
					elem_name = elem_node.tagName
					if option_list.count(elem_name) == 0 :
						option_list.append(elem_name)

		page_num = self.notebook.get_current_page()
		if page_num >= 0 :
			current_type = self.pages[page_num]
		else :
			current_type = None

		if len(option_list) == 0 and not elem_is_any_name :
			return 0
		elif len(option_list) == 1 and not elem_is_any_name and not invoked_by_wizard \
				and ((validate_type == "dtd" and option_list[0] != "lifetime")
					or (validate_type != "dtd" and option_list[0][0][1].getAttribute("name") != "lifetime")) :
			obj_type = option_list[0]
		elif not invoked_by_wizard and mode_level == 0 and (
					self.obj_type in ["node", "primitive", "template", "group"]
					or (self.obj_type in ["clone", "master"]
						and (self.pages.count("primitive") > 0 
							or self.pages.count("group") > 0))
					) :
			if self.obj_type in ["clone", "master"] \
					and (self.pages.count("primitive") > 0 or self.pages.count("group") > 0) \
					and current_type in ["primitive", "group"] :
				return 0
			obj_type = current_type
		else :
			dialog = gtk.Dialog(_("Add"), top_window, gtk.DIALOG_MODAL,
				(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK))
			dialog.set_border_width(5)
			dialog.set_default_response(gtk.RESPONSE_OK)

			if append_title != "" :
				label = gtk.Label(append_title)
				label.set_markup('<big><b>' + append_title + '</b></big>')
				label.set_alignment(0, 0)
				dialog.vbox.pack_start(label, False, padding=2)

				separator = gtk.HSeparator()
				dialog.vbox.pack_start(separator, False, padding = 2)


			radio_btns = {}
			radio_btn = None
			for option in option_list :
				if type(option) == str or type(option) == unicode :
					opt_name = option
				else :
					opt_name = option[0][1].getAttribute("name")

				if opt_name == "" :
					continue

				if invoked_by_wizard and opt_name in ["meta_attributes", "instance_attributes", "operations"] :
					continue

				radio_btn = gtk.RadioButton(radio_btn, _(name_cap(opt_name)))
				if opt_name == current_type :
					radio_btn.set_active(True)
				dialog.vbox.pack_start(radio_btn, False, padding=2)
				radio_btns[radio_btn] = option

			if elem_is_any_name :
				radio_btn = gtk.RadioButton(radio_btn, _("Other") + _(":"))
				entry = gtk.Entry()
				entry.set_activates_default(True)

				hbox = gtk.HBox()
				hbox.pack_start(radio_btn, False, padding=2)
				hbox.pack_start(entry, True, padding=2)

				dialog.vbox.pack_start(hbox, False, padding=2)
				radio_btns[radio_btn] = entry

			if len(radio_btns) == 0 :
				return 0

			save_top_window = top_window
			top_window = dialog
			dialog.vbox.show_all()

			while True :
				ret = dialog.run()
				if ret == gtk.RESPONSE_OK :
					passed = True
					for radio_btn in radio_btns :
						if radio_btn.get_active() :
							obj_type = radio_btns[radio_btn]
							if type(obj_type) == gtk.Entry and obj_type.get_text() == "" :
								msgbox(top_window, _("Please specify the type of object you want to add"))
								passed = False
							break
					if passed :
						break
				else :
					obj_type = None
					break

			top_window = save_top_window
			dialog.destroy()

			if obj_type == None :
				return 0

		if validate_type == "dtd" :
			obj_type_name = obj_type
		else :
			if type(obj_type) == str or type(obj_type) == unicode :
				obj_type_name = obj_type
				#sorted_rng_nodes = manager.sorted_sub_rng_nodes_by_name(obj_type_name)
			elif type(obj_type) == gtk.Entry :
				obj_type_name = obj_type.get_text()
				#sorted_rng_nodes = manager.sorted_sub_rng_nodes_by_name(obj_type_name)
			else :
				obj_type_name = obj_type[0][1].getAttribute("name")
				#sorted_rng_nodes = manager.sorted_sub_rng_nodes_by_node(*obj_type[0])

		(parent_xml_node, add_obj_type, new_mid_elem) = manager.real_add_obj_type(self.xml_node, obj_type_name)
		if parent_xml_node == None :
			return 1
				
		if obj_type_name not in manager.get_supported_rsc_types() :
			add_mode = "dialog"
		elif invoked_by_wizard or mode_level == 0 :
			add_mode = "wizard"
		else :
			dialog = gtk.Dialog("Select Mode", top_window, gtk.DIALOG_MODAL,
				(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK))
			dialog.set_border_width(5)
			dialog.set_default_response(gtk.RESPONSE_OK)

			wizard_radio_btn = gtk.RadioButton(None, _("Wizard"))
			dialog.vbox.pack_start(wizard_radio_btn, False, padding=2)

			dialog_radio_btn = gtk.RadioButton(wizard_radio_btn, _("Dialog"))
			dialog.vbox.pack_start(dialog_radio_btn, False, padding=2)

			save_top_window = top_window
			top_window = dialog
			dialog.vbox.show_all()

			ret = dialog.run()

			if ret == gtk.RESPONSE_OK :
				if wizard_radio_btn.get_active() :
					add_mode = "wizard"
				else :
					add_mode = "dialog"
			else :
				add_mode = None

			top_window = save_top_window
			dialog.destroy()

			if add_mode == None :
				return 1

		impl = getDOMImplementation()
		newdoc = impl.createDocument(None, add_obj_type, None)
		new_elem = newdoc.documentElement
		parent_xml_node.appendChild(new_elem)

		if add_mode == "wizard" :
			objdlg = AddWizard(new_elem)
		else :
			objdlg = ObjectViewDlg(new_elem, True)

		while True :
			new_xml_node = objdlg.run()
			if new_xml_node == None :
				tmp_elem = objdlg.obj_view.xml_node
				tmp_elem.parentNode.removeChild(tmp_elem)
				if new_mid_elem != None :
					new_mid_elem.parentNode.removeChild(new_mid_elem)
				if self.is_topview and window.cur_view != None :
					window.cur_view.update()
				return 2
			if not self.is_topview :
				objdlg.destroy()
				self.new_page_type = obj_type_name
				self.on_changed()
				if self.change_call_back != None :
					self.change_call_back()
				return 3
			else :
				if self.is_fake_xml_node :
					parent_xml_node = self.xml_node.cloneNode(True)
					#parent_xml_node.appendChild(new_xml_node)
					xml_str = parent_xml_node.toxml().replace("\n", "")
					parent_type = self.missing_opt_obj_parent_type
					if parent_type == None :
						if parent_xml_node.tagName != "node_state" :
							parent_type = "configuration"
						else :
							parent_type = "status"
					manager.cib_do_cmd("cib_create\n%s\n%s"%(str(parent_type), str(xml_str)))
				else :
					if not manager.validate_cib(init_cib_xml_node) :
						continue
					#xml_str = new_xml_node.toxml().replace("\n", "")
					#parent_type = self.obj_type
					xml_str = self.xml_node.toxml().replace("\n", "")
					manager.cib_do_cmd("cib_replace\n%s\n%s"%(str(self.obj_type), str(xml_str)))

				self.update()
				if manager.failed_reason != "" :
					msgbox(top_window, manager.failed_reason)
				else :
					if manager.active_cib != "" :
						manager.set_update()
					objdlg.destroy()
					self.new_page_type = obj_type_name

					#add pingd location
					self.add_ping_location(new_elem.getAttribute('id'))

					return 3

	def add_ping_location(self, rsc_name):
		add_location = False
		for resource in manager.xml_nodes["cib"].getElementsByTagName("primitive") :
			if resource.getAttribute('type') == "ping" and resource.getAttribute('provider') == "common" and resource.getAttribute('class') == "ocf" \
				and resource.parentNode.tagName == "clone":
				ping_rsc = resource.getAttribute('id')
				status = manager.get_rsc_status(str(ping_rsc))[0]
				if status == 'running' or status == 'running (Master)' or status == 'running (Slave)':
					add_location = True
					break

		if not add_location :
			return

		xml_constraints = manager.xml_nodes["cib"].getElementsByTagName("constraints")[0]

		impl = getDOMImplementation()
		newdoc = impl.createDocument(None, "rsc_location", None)
		new_location = newdoc.documentElement
		new_location.setAttribute('id', rsc_name + "--location--pingd")
		new_location.setAttribute('rsc', rsc_name)

		newdoc = impl.createDocument(None, "rule", None)
		new_rule = newdoc.documentElement
		new_rule.setAttribute('id', "prefered--" + rsc_name + "--location--pingd")
		new_rule.setAttribute('score', "-INFINITY")
		new_rule.setAttribute('boolean-op', "or")

		newdoc = impl.createDocument(None, "expression", None)
		new_exp1 = newdoc.documentElement
		new_exp1.setAttribute("id", rsc_name + "--ping--exclude")
		new_exp1.setAttribute("attribute", "pingd")
		new_exp1.setAttribute("operation", "not_defined")
		new_rule.appendChild(new_exp1)

		newdoc = impl.createDocument(None, "expression", None)
		new_exp2 = newdoc.documentElement
		new_exp2.setAttribute("id", rsc_name + "--ping--prefer")
		new_exp2.setAttribute("attribute", "pingd")
		new_exp2.setAttribute("operation", "lte")
		new_exp2.setAttribute("value", "0")
		new_rule.appendChild(new_exp2)

		new_location.appendChild(new_rule)

		xml_constraints.appendChild(new_location)

		xml_str = xml_constraints.toxml().replace("\n", "")
                manager.cib_do_cmd("cib_replace\n%s\n%s"%(str("constraints"), str(xml_str)))
                if manager.failed_reason != "" :
                	msgbox(top_window, manager.failed_reason)

		return

	def get_elem_options_dtd(self) :
		(sep,cont,mod) =  self.dtd_elem.get_content_model()
		option_list = []
		if mod == "*" :
			for sub in cont :
				if len(sub) == 2 :
					option_list.append(sub[0])
		else :
			if sep != "|" :
				for sub in cont :
					if len(sub) == 2 :
						if sub[1] == "*" or sub[1] == "+":
							option_list.append(sub[0])
						elif sub[1] == "" or sub[1] == "?" :
							elem_node_list = []
							for elem_node in self.xml_node.getElementsByTagName(sub[0]) :
								if elem_node in self.xml_node.childNodes :
									elem_node_list.append(elem_node)
							if len(elem_node_list) < 1 or \
									len(manager.get_dtd_elem(sub[0]).get_attr_list()) == 0 :
								option_list.append(sub[0])

		return option_list

	def get_elem_options_rng(self) :
		attr_rng_node_dict = self.attr_rng_node_dict
		elem_rng_node_dict = self.elem_rng_node_dict

		object_attrs = {}
		for (k, v) in self.xml_node.attributes.items() :
			object_attrs[k] = v

		ref_match_value_decl_nodes_list = []
		ref_decl_nodes_list = []
		for key in object_attrs :
			for attr_rng_node in attr_rng_node_dict.get(key, []) :
				decl_rng_nodes = manager.get_decl_rng_nodes(attr_rng_node)
				value_list = []
				sub_rng_nodes = manager.sorted_sub_rng_nodes_by_node(*attr_rng_node[0])
				for value_node in sub_rng_nodes.get("value", []) :
					value_list.append(value_node[0][1].childNodes[0].data)
				if object_attrs.get(key, "") in value_list :
					ref_match_value_decl_nodes_list.append(decl_rng_nodes)
				elif len(sub_rng_nodes.get("data", [])) > 0 or len(sub_rng_nodes.get("text", [])) > 0 :
					ref_decl_nodes_list.append(decl_rng_nodes)

		if len(ref_match_value_decl_nodes_list) > 0 :
			ref_decl_nodes_list = ref_match_value_decl_nodes_list

		ref_sorted_nodes = {}
		for decl_type in ["choice", "first_choice", "group", "first_group"] :
			ref_sorted_nodes[decl_type] = manager.get_sorted_decl_nodes(ref_decl_nodes_list, decl_type)

		elem_node_dict = {}
		for elem_node in self.xml_node.childNodes :
			if elem_node.nodeType != xml.dom.Node.ELEMENT_NODE :
				continue
			elem_type = elem_node.tagName
			if not elem_node_dict.has_key(elem_type) :
				elem_node_dict[elem_type] = []
			elem_node_dict[elem_type].append(elem_node)

		exist_elem_rng_nodes = []
		ref_elem_decl_nodes_list = []
		for key in elem_node_dict :
			for elem_rng_node in elem_rng_node_dict.get(key, []):
				if len(elem_node_dict[key]) > 1 and manager.find_decl(elem_rng_node, "oneOrMore") == 0 \
						and manager.find_decl(elem_rng_node, "zeroOrMore") == 0 :
					continue
				exist_elem_rng_nodes.append(elem_rng_node)
				decl_rng_nodes = manager.get_decl_rng_nodes(elem_rng_node)
				ref_elem_decl_nodes_list.append(decl_rng_nodes)

		ref_elem_sorted_nodes = {}
		for decl_type in ["choice", "first_choice", "group", "first_group"] :
			ref_elem_sorted_nodes[decl_type] = manager.get_sorted_decl_nodes(ref_elem_decl_nodes_list, decl_type)

		option_list = []
		for rng_node in self.elem_rng_nodes :
			name = rng_node[0][1].getAttribute("name")

			if option_list.count(name) > 0 :
				continue

			can_add = True 
			
			if rng_node not in exist_elem_rng_nodes :
				decl_rng_nodes = manager.get_decl_rng_nodes(rng_node)
				if decl_rng_nodes.get("choice") != None :
					for sorted_nodes in [ref_sorted_nodes, ref_elem_sorted_nodes] :
						if decl_rng_nodes["choice"] in sorted_nodes["choice"] :
							if manager.find_decl(rng_node, "zeroOrMore") != 0 and \
									manager.find_decl(rng_node, "zeroOrMore") > \
										manager.find_decl(rng_node, "choice") :
								continue
							if manager.find_decl(rng_node, "oneOrMore") != 0 and \
									manager.find_decl(rng_node, "oneOrMore") > \
										manager.find_decl(rng_node, "choice") :
								continue
							if len(sorted_nodes["group"]) == 0 :
									can_add = False
							else :
								if decl_rng_nodes.get("group") not in sorted_nodes["group"] :
									can_add = False
								elif decl_rng_nodes.get("first_choice") in sorted_nodes["first_choice"] and \
										decl_rng_nodes.get("first_group") not in sorted_nodes["first_group"] :
									can_add = False

			if not can_add :
				continue

			if manager.find_decl(rng_node, "zeroOrMore") != 0 or manager.find_decl(rng_node, "oneOrMore") != 0 :
				option_list.append(rng_node)
			else :
				sub_rng_nodes = manager.sorted_sub_rng_nodes_by_node(*rng_node[0])
				if len(elem_node_dict.get(name, [])) < 1 or len(sub_rng_nodes.get("attribute", [])) == 0 \
						or (mode_level != 2 and name in ["operations"]):
					option_list.append(rng_node)
		return option_list
							

	def on_edit(self, widget) :
		init_cib_xml_node = manager.xml_nodes["cib"]

		selected_node = self.get_selected_node()
		if selected_node == None :
			return
		objdlg = ObjectViewDlg(selected_node, False)
		while True :
			new_xml_node = objdlg.run()
			if new_xml_node == None :
				if not self.is_topview :
					self.on_changed()
				else :
					if window.cur_view != None :
						window.cur_view.update()
				return
			if not self.is_topview :
				objdlg.destroy()
				self.on_changed()
				if self.change_call_back != None :
					self.change_call_back()
				return
			else :
				if not manager.validate_cib(init_cib_xml_node) :
					continue
				#if new_xml_node.getAttribute("id") != "" :
				#	xml_str = new_xml_node.toxml().replace("\n", "")
				#else :
				#	xml_str = new_xml_node.parentNode.toxml().replace("\n", "")
				xml_str = self.xml_node.toxml().replace("\n", "")

				manager.cib_do_cmd("cib_replace\n%s\n%s"%(str(self.obj_type), str(xml_str)))
				self.update()
				if manager.failed_reason != "" :
					msgbox(top_window, manager.failed_reason)
				else :
					if window.cur_view != None :
						window.cur_view.update()
					objdlg.destroy()
					return

	def on_del(self, widget) :
		selected_node = self.get_selected_node()
		if selected_node == None :
			return

		if selected_node.tagName == "node" and selected_node.getAttribute("id") in manager.get_dc():
			msgbox(top_window, _("Please do not delete the DC node!"))
			return

		ret = confirmbox(top_window, _("This will delete the %s \"%s\"")%(_(name_cap(selected_node.tagName)), selected_node.getAttribute("id")),
				(gtk.STOCK_NO, gtk.RESPONSE_NO, gtk.STOCK_YES, gtk.RESPONSE_YES),
				_("Delete the selected object?"))
		if ret == gtk.RESPONSE_YES :
			if selected_node.tagName == "node" :
				del_node_id = None
				cmd = "crm_node -l"
				ret = manager.do_cmd("system\n%s"%(str(cmd)))
				if manager.failed_reason != "":
					msgbox(top_window, manager.failed_reason)
				try:
					for r in ret :
						if r.split()[1] == selected_node.getAttribute("id"):
							del_node_id = r.split()[0]
							break
				except:
					pass

				manager.del_node_constraints(selected_node.getAttribute("id"))
				if del_node_id != None:
					cmd = "crm_node --force -R %s"%(str(del_node_id))
					manager.do_cmd("system\n%s"%(str(cmd)))
					if manager.failed_reason != "":
						msgbox(top_window, manager.failed_reason)

			selected_node.parentNode.removeChild(selected_node)
			if not self.is_topview :
				self.on_changed()
				if self.change_call_back != None :
					 self.change_call_back()
			else :
				#manager.validate_cib()
				#xml_str = selected_node.toxml().replace("\n", "")
				#manager.cib_do_cmd("cib_delete\n%s\n%s"%(str(self.obj_type), str(xml_str)))
				#if manager.failed_reason != "" :
				#	msgbox(top_window, manager.failed_reason)

				if manager.validate_cib() :
					xml_str = selected_node.toxml().replace("\n", "")
					manager.cib_do_cmd("cib_delete\n%s\n%s"%(str(self.obj_type), str(xml_str)))
					if manager.failed_reason != "" :
						msgbox(top_window, manager.failed_reason)
						if manager.active_cib != "" :
							manager.set_update()
					elif manager.active_cib != "" :
						self.on_changed()
				else :
					manager.set_update()
				self.update()

	def on_up(self, widget) :
		elem_list = self.get_elem_list()
		if elem_list == None :
			return

		(model, iter) = elem_list.tree.get_selection().get_selected()
		if iter == None or model.get_path(iter)[-1] == 0 :
			return

		(type, id) =  elem_list.get_node_key(model, iter)

		path = model.get_path(iter)
		if path[-1] < 1 :
			return
		prev_path_list = list(path[:])
		prev_path_list[-1] = prev_path_list[-1] - 1
		prev_path = tuple(prev_path_list)

		prev_iter = model.get_iter(prev_path)
		(prev_type, prev_id) = elem_list.get_node_key(model, prev_iter)

		selected_node = elem_list.nodes[(type, id)]
		prev_node = elem_list.nodes[(prev_type, prev_id)]

		try :
			selected_node.parentNode.insertBefore(selected_node.cloneNode(True), prev_node)
		except :
			return

		selected_node.parentNode.removeChild(selected_node)

		if self.is_topview :
			if manager.validate_cib() :
				xml_str = self.xml_node.toxml().replace("\n", "")
				manager.cib_do_cmd("cib_replace\n%s\n%s"%(str(self.obj_type), str(xml_str)))
				if manager.failed_reason != "" :
					msgbox(top_window, manager.failed_reason)
					if manager.active_cib != "" :
						manager.set_update()
				else :
					self.on_changed()
			else :
				manager.set_update()
		else :
			self.on_changed()
			if self.change_call_back != None :
				self.change_call_back()
		#self.update()

	def on_down(self, widget) :
		elem_list = self.get_elem_list()
		if elem_list == None :
			return

		(model, iter) = elem_list.tree.get_selection().get_selected()
		if iter == None or model.iter_next(iter) == None :
			return

		(type, id) =  elem_list.get_node_key(model, iter)
		selected_node = elem_list.nodes[(type, id)]

		n_iter = model.iter_next(iter)
		nn_iter = model.iter_next(n_iter)

		if nn_iter == None :
			try :
				selected_node.parentNode.appendChild(selected_node.cloneNode(True))
			except :
				return
		else :
			(nn_type, nn_id) = elem_list.get_node_key(model, nn_iter)
			nn_node = elem_list.nodes[(nn_type, nn_id)]
			try :
				selected_node.parentNode.insertBefore(selected_node.cloneNode(True), nn_node)
			except :
				return
		selected_node.parentNode.removeChild(selected_node)

		if self.is_topview :
			if manager.validate_cib() :
				xml_str = self.xml_node.toxml().replace("\n", "")
				manager.cib_do_cmd("cib_replace\n%s\n%s"%(str(self.obj_type), str(xml_str)))
				if manager.failed_reason != "" :
					msgbox(top_window, manager.failed_reason)
					if manager.active_cib != "" :
						manager.set_update()
				else :
					self.on_changed()
			else :
				manager.set_update()
		else :
			self.on_changed()
			if self.change_call_back != None :
				self.change_call_back()
		#self.update()

	def on_changed(self) :
		notebook_status = self.save_status()
		self.update()
		if notebook_status != None :
			self.restore_status(notebook_status)
		else :
			self.on_after_show()

	def save_status(self) :
		page_num = self.notebook.get_current_page()
		if page_num < 0 :
			return None

		page_type = self.pages[page_num]

		new_page_type = self.new_page_type
		self.new_page_type = None

		tree_status = {}
		for i in range(len(self.elem_lists)) :
			tree_status[self.pages[i]] =  self.elem_lists[i].save_tree_status()
		return (page_type, new_page_type, tree_status)

	def restore_status(self, notebook_status) :
		(page_type, new_page_type, tree_status) = notebook_status

		if new_page_type != None :
			set_page_type = new_page_type
		else :
			set_page_type = page_type

		for i in range(len(self.elem_lists)) :
			page_name = self.pages[i]
			if page_name == set_page_type :
				self.notebook.set_current_page(i)
			if tree_status.get(page_name) != None :
				self.elem_lists[i].restore_tree_status(tree_status[page_name])
		self.on_after_show()
		
class AddWizard :
	current_page = None
	def __init__(self, xml_node) :
		self.xml_node = xml_node
		self.obj_type = xml_node.tagName

		common_options = [
		("target-role", [["", "Defaults to \"Started\" or inherit from its parent"], ["Started", ""], ["Stopped", ""]],
			_("Initial state of resource")),
		]

		clone_basic_options = [
		("clone-max", [],
		 _("Maximum number of copies (Defaults to the number of nodes in the cluster)")),
		("clone-node-max", [["1", _("[ default ]")]],
		 _("Maximum number of copies on a single node (Defaults to 1)")),
		]
		clone_other_options = [
		("notify", [["false", _("[ default ]")], ["true", ""]],
		 _("Notify all the other copies before stopping or starting a copy and when the action was successful (Defaults to false)")),
		("globally-unique", [["false", _("[ default ]")], ["true", ""]],
		 _("Globally Unique (Does each copy of the clone perform a different function? Defaults to false)")),
		("interleave", [["false", _("[ default ]")], ["true", ""]],
		 _("Interleave (Changes the behavior of ordering constraints (between clones/masters) so that instances can start/stop as soon as their peer instance has (rather than waiting for every instance of the other clone has). Defaults to false)")),
		]
		#neoshineha ming.liu add
                master_other_options = [
                ("notify", [["1", _("[ default ]")], ["true", ""]],
                 _("Notify all the other copies before stopping or starting a copy and when the action was successful (Defaults to false)")),
                ("globally-unique", [["false", _("[ default ]")], ["true", ""]],
                 _("Globally Unique (Does each copy of the clone perform a different function? Defaults to false)")),
                ("interleave", [["false", _("[ default ]")], ["true", ""]],
                 _("Interleave (Changes the behavior of ordering constraints (between clones/masters) so that instances can start/stop as soon as their peer instance has (rather than waiting for every instance of the other clone has). Defaults to false)")),
                ]
		#neoshineha ming.liu end

		master_basic_options = [
		("master-max", [["1", _("[ default ]")]],
		 _("Maximum number of master copies (Defaults to 1)")),
		("master-node-max", [["1", _("[ default ]")]],
		 _("Maximum number of master copies on a single node (Defaults to 1)"))
		]

		meta_attributes_options = {
		"primitive": common_options,
		"group": common_options,
		"clone": common_options + clone_basic_options + clone_other_options,
		"master": common_options + clone_basic_options + master_basic_options + master_other_options,
		}
		self.meta_attributes_options = meta_attributes_options

		self.default_meta_attributes = {}
		for option in meta_attributes_options[self.obj_type] :
			if validate_type == "dtd" :
				key = option[0].replace("-", "_")
			else :
				key = option[0]
			for (value, decl) in option[1] :
				if decl.count(_("[ default ]")) > 0 :
					self.default_meta_attributes[key] = value

	def first_page_render(self) :
		title = _("Add") + " " + _(name_cap(self.xml_node.tagName))
		dialog = gtk.Dialog(title, top_window, gtk.DIALOG_MODAL,
			(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_GO_FORWARD, gtk.RESPONSE_OK))
		dialog.set_border_width(5)
		dialog.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_NORMAL)
		dialog.set_default_response(gtk.RESPONSE_OK)
		self.dialog = dialog
		self.current_page = 0

		label = gtk.Label()
		label_text = title + " - " + _("Basic Settings")
		label.set_markup('<big><b>' + label_text + '</b></big>')
		label.set_alignment(0, 0)
		label.show()
		dialog.vbox.pack_start(label, False, padding = 2)

		separator = gtk.HSeparator()
		separator.show()
		dialog.vbox.pack_start(separator, False, padding = 2)

		if self.obj_type in ["primitive", "template"] :
			obj_attrs = Primitive(self.xml_node, True, hide_optional = True)
		else :
			obj_attrs = obj_attrs = ObjectAttrs(self.xml_node, True, hide_optional = True)
		obj_attrs.update()
		obj_attrs.on_after_show()

		dialog.vbox.pack_start(obj_attrs.attrs_vbox)
		self.obj_attrs = obj_attrs
		self.obj_view = obj_attrs

		label = gtk.Label()
		label.set_markup('<b>' + _("Options") + '</b>')
		label.set_alignment(0, 1)
		label.show()
		dialog.vbox.pack_start(label, False, padding = 2)

		meta_attributes = self.get_meta_attributes()

		combos = {}
		checkbuttons = {}
		spinbuttons = {}

		self.num_buttons_map = {}

		for option in self.meta_attributes_options[self.obj_type] :
			if validate_type == "dtd" :
				key = option[0].replace("-", "_")
			else :
				key = option[0]

			is_boolean = False
			for value in option[1] :
				if value[0] in ["true", "false"] :
					is_boolean = True
					break

			hbox = gtk.HBox()
			if not is_boolean :
				name_label = gtk.Label(option[2] + _(":"))
				name_label.set_alignment(0, 0.5)

				if key.count("max") > 0 :
					num_checkbutton = gtk.CheckButton()
					num_checkbutton.add(name_label)

					num_checkbutton.connect("toggled", self.on_num_checkbutton_toggled)
					if meta_attributes.get(key, "") != "" :
						num_checkbutton.set_active(True)
					
					hbox.pack_start(num_checkbutton, False, padding=2)
				else :
					hbox.pack_start(name_label, False, padding=2)

			if is_boolean :
				label = gtk.Label(option[2])
				label.set_line_wrap(True)
				widget = gtk.CheckButton()
				widget.add(label)

				checkbuttons[key] = widget
				hbox.pack_start(widget, True, padding=2)
			elif key.count("max") > 0 :
				if key in ["clone-max", "clone_max"] :
					node_list = manager.get_normal_nodes()
					if node_list != None and len(node_list) > 0 :
						init_value = len(node_list)
					else :
						init_value = 1
				else :
					init_value = 1

				adj = gtk.Adjustment(init_value, 1, 999, 1, 3)
				widget = gtk.SpinButton(adj, 0, 0)
				widget.set_width_chars(3)
				widget.set_wrap(True)

				if meta_attributes.get(key, "") == "" :
					widget.set_sensitive(False)

				self.num_buttons_map[num_checkbutton] = widget

				hbox.pack_start(widget, False)
				spinbuttons[key] = widget
			else :
				store = gtk.ListStore(str, str)
				for value in option[1] :
					store.append(value)

				widget = gtk.ComboBox(store)
				cell0 = gtk.CellRendererText()
				cell1 = gtk.CellRendererText()
				widget.pack_start(cell0, True)
				widget.pack_start(cell1, True)
				widget.add_attribute(cell0, 'text', 0)
				widget.add_attribute(cell1, 'text', 1)

				combos[key] = widget
				hbox.pack_start(widget, True, padding=2)

			hbox.show_all()
			dialog.vbox.pack_start(hbox, False, padding=2)

		widgets = {}
		widgets["combos"] = combos
		widgets["checkbuttons"] = checkbuttons
		widgets["spinbuttons"] = spinbuttons
		widget_group = WidgetGroup(widgets)
		self.widget_group = widget_group

		if self.obj_type in ["primitive", "template"] :
			label = gtk.Label(_("Add monitor operation"))
			self.monitor_checkbutton = gtk.CheckButton()
			self.monitor_checkbutton.add(label)
			self.monitor_checkbutton.show_all()
			dialog.vbox.pack_start(self.monitor_checkbutton, False, padding=2)

	def on_num_checkbutton_toggled(self, widget) :
		spinbutton = self.num_buttons_map.get(widget)
		if spinbutton != None :
			spinbutton.set_sensitive(widget.get_active())

	def get_meta_attributes(self) :
		meta_attributes = {}
		for meta_attributes_node in self.xml_node.getElementsByTagName("meta_attributes") :
			for nv_xml_node in meta_attributes_node.getElementsByTagName("nvpair") :
				attribute_name = nv_xml_node.getAttribute("name")
				meta_attributes[attribute_name] = nv_xml_node.getAttribute("value")
			break
		return meta_attributes

	def first_page_update(self) :
		meta_attributes = self.get_meta_attributes()
		tmp_meta_attributes = self.default_meta_attributes.copy()
		tmp_meta_attributes.update(meta_attributes)
		self.widget_group.show_values(tmp_meta_attributes)

		if self.obj_type in ["primitive", "template"] :
			monitors = self.get_monitors()
			if len(monitors) > 0 :
				self.monitor_checkbutton.set_active(True)
			else :
				self.monitor_checkbutton.set_active(False)

	def first_page_run(self) :
		global top_window
		dialog = self.dialog
		dialog.vbox.show()
		save_top_window = top_window
		top_window = dialog

		while True :
			ret = dialog.run()

			if ret == gtk.RESPONSE_OK :
				passed = self.obj_attrs.verify_values()
				if not passed :
					continue
				dialog.destroy()
				top_window = save_top_window

				self.set_meta_attributes()
				if self.obj_type in ["primitive", "template"] :
					meta = self.get_rsc_meta()
					self.set_monitor(meta)
					self.set_inst_attributes(meta)
				return self.last_page(True)
			else :
				dialog.destroy()
				top_window = save_top_window
				return None

	def set_meta_attributes(self) :
		meta_attributes = self.widget_group.get_values()

		(parent_xml_node, add_obj_type, new_mid_elem) = manager.real_add_obj_type(self.xml_node, "meta_attributes", True)
		if parent_xml_node == None :
			return

		nv_xml_nodes = {}
		for nv_xml_node in parent_xml_node.getElementsByTagName("nvpair") :
			nv_name = nv_xml_node.getAttribute("name")
			nv_xml_nodes[nv_name] = nv_xml_node

		impl = getDOMImplementation()
		for attr_name in meta_attributes :
			nv_xml_node = nv_xml_nodes.get(attr_name)
			if attr_name.count("max") > 0 :
				value = meta_attributes[attr_name].split(".")[0]
			else :
				value = meta_attributes[attr_name]

			if nv_xml_node != None :
				#if value != self.default_meta_attributes.get(attr_name) :
					nv_xml_node.setAttribute("value", value)
				#else :
				#	nv_xml_node.parentNode.removeChild(nv_xml_node)
			else :
				if value != self.default_meta_attributes.get(attr_name) :
					newdoc = impl.createDocument(None, "nvpair", None)
					nv = newdoc.documentElement
					parent_xml_node.appendChild(nv)

					attr_id = manager.auto_unique_id(nv, attr_name)
					nv.setAttribute("id", attr_id)
					nv.setAttribute("name", attr_name)
					nv.setAttribute("value", value)

		for option in self.meta_attributes_options[self.obj_type] :
			if validate_type == "dtd" :
				attr_name = option[0].replace("-", "_")
			else :
				attr_name = option[0]

			nv_xml_node = nv_xml_nodes.get(attr_name)
			if nv_xml_node != None and meta_attributes.get(attr_name, "") == "" :
				nv_xml_node.parentNode.removeChild(nv_xml_node)


		if len(parent_xml_node.getElementsByTagName("nvpair")) == 0 :
			parent_xml_node.parentNode.removeChild(parent_xml_node)

	def get_monitors(self) :
		monitors = []
		for operations_node in self.xml_node.getElementsByTagName("operations") :
			for op_node in operations_node.getElementsByTagName("op") :
				op_name = op_node.getAttribute("name")
				if op_name == "monitor" :
					monitors.append(op_node)
		return monitors

	def get_rsc_meta(self) :
		primitive_attrs = manager.get_rsc_attrs(self.xml_node, ["class", "type", "provider"])
		primitive_class = str(primitive_attrs.get("class", ""))
		primitive_type = str(primitive_attrs.get("type", ""))
		primitive_provider = str(primitive_attrs.get("provider", ""))
		meta = manager.get_rsc_meta(primitive_class, primitive_type, primitive_provider)
                if primitive_class == 'stonith':
                        pcmk_host_list = {'content': {'default': "", 'type': "string"},
                                          'longdesc': "A list of machines controlled by this device.", 'name': "pcmk_host_list",
                                          'required': "1", 'shortdesc': "", 'unique': "", 'value': ""}
                        meta.parameters.append(pcmk_host_list)
		return meta

	def set_monitor(self, meta) :
		if self.obj_type not in ["primitive", "template"] or meta == None :
			return

		monitors = self.get_monitors()
		(parent_xml_node, add_obj_type, new_mid_elem) = manager.real_add_obj_type(self.xml_node, "operations", True)
		if parent_xml_node == None :
			return

		enable_monitor = self.monitor_checkbutton.get_active()
		if enable_monitor :
			if len(monitors) == 0 :
				impl = getDOMImplementation()

				if validate_type == "dtd" :
					dtd_elem = manager.get_dtd_elem(add_obj_type)
					attr_list = dtd_elem.get_attr_list()
				else :
					attr_list = []
					sorted_rng_nodes = manager.sorted_sub_rng_nodes_by_name(add_obj_type)
					if sorted_rng_nodes != None :
						attr_rng_nodes = sorted_rng_nodes.get("attribute", [])
						for rng_node in attr_rng_nodes :
							name = rng_node[0][1].getAttribute("name")
							if attr_list.count(name) == 0 :
								attr_list.append(name)

				default_interval = "10"
				for action in meta.actions :
					if action.get("name") == "monitor" :
						newdoc = impl.createDocument(None, add_obj_type, None)
						op = newdoc.documentElement
						parent_xml_node.appendChild(op)

						primitive_id = str(self.xml_node.getAttribute("id"))
						op_id = primitive_id + "-" + add_obj_type + "-" + action["name"]
						role = action.get("role", "")
						if role != "" : 
							op_id += "-" + role
						interval = action.get("interval", "")
						if interval == "" :
							interval = default_interval

						op_id += "-" + interval
						unique_id = manager.get_unique_id(op_id, op)
						op.setAttribute("id", unique_id)

						for attr_name in attr_list :
							key  = attr_name.replace("_", "-")
							value = action.get(key, "")
							if value != "" :
								op.setAttribute(key, action[key])
							else :
								if key == "interval" :
									op.setAttribute(key, default_interval)

			else :
				return
				
		else :
			for monitor in monitors :
				monitor.parentNode.removeChild(monitor)

		ops = []
		for operations_node in self.xml_node.getElementsByTagName("operations") :
			for op_node in operations_node.getElementsByTagName("op") :
				op_name = op_node.getAttribute("name")
				ops.append(op_node)
		if len(ops) == 0 :
			parent_xml_node.parentNode.removeChild(parent_xml_node)

	def set_inst_attributes(self, meta) :
		if self.obj_type not in ["primitive", "template"] or meta == None :
			return

		(parent_xml_node, add_obj_type, new_mid_elem) = manager.real_add_obj_type(self.xml_node, "instance_attributes", True)
		if parent_xml_node == None :
			return

		nv_xml_nodes = {}
		for nv_xml_node in parent_xml_node.getElementsByTagName("nvpair") :
			nv_name = nv_xml_node.getAttribute("name")
			nv_xml_nodes[nv_name] = nv_xml_node

		impl = getDOMImplementation()

		param_list = []
		for param in meta.parameters :
			attr_name = param.get("name", "")
			if attr_name == "" :
				continue

			param_list.append(attr_name)

			if nv_xml_nodes.get(attr_name) != None :
				continue

			if param.get("required") == "1" :
				newdoc = impl.createDocument(None, "nvpair", None)
				nv = newdoc.documentElement
				parent_xml_node.appendChild(nv)

				attr_id = manager.auto_unique_id(nv, attr_name)
				nv.setAttribute("id", attr_id)
				nv.setAttribute("name", attr_name)

		for nv_name in nv_xml_nodes :
			if nv_name not in param_list :
				nv_xml_nodes[nv_name].parentNode.removeChild(nv_xml_nodes[nv_name])

		if len(parent_xml_node.getElementsByTagName("nvpair")) == 0 :
			parent_xml_node.parentNode.removeChild(parent_xml_node)

	def first_page_init_run(self) :
		self.first_page_render()
		self.first_page_update()

		if validate_type == "dtd" :
			target_role_widget = self.widget_group.widgets["combos"].get("target_role")
		else :
			target_role_widget = self.widget_group.widgets["combos"].get("target-role")
		if target_role_widget != None :
			if self.xml_node.parentNode.tagName == "resources" and manager.active_cib == "" :
				default_value = "Stopped"
			else :
				default_value = ""
				
			model = target_role_widget.get_model()
			iter = model.get_iter_first()
			while iter != None :
				if model.get_value(iter,0) == default_value :
					target_role_widget.set_active_iter(iter)
					break
				iter = model.iter_next(iter)

		if self.obj_type in ["primitive", "template"] :
			self.monitor_checkbutton.set_active(True)

		return self.first_page_run()

	def first_page_update_run(self) :
		self.first_page_render()
		self.first_page_update()
		return self.first_page_run()

	def last_page(self, add_prompt = False) :
		global top_window
		title = _("Add") + " " + _(name_cap(self.obj_type))
		dialog = gtk.Dialog(title, top_window, gtk.DIALOG_MODAL,
			(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_GO_BACK, gtk.RESPONSE_REJECT, gtk.STOCK_APPLY, gtk.RESPONSE_APPLY))
		dialog.set_border_width(5)
		dialog.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_NORMAL)
		dialog.set_default_response(gtk.RESPONSE_APPLY)

		self.current_page = 1

		label_text = title + " - "
		rsc_id = self.xml_node.getAttribute("id")
		if rsc_id != "" :
			label_text += _("Summary Of \"%s\"")%rsc_id
		else :
			label_text += _("Summary")

		label = gtk.Label()
		label.set_markup('<big><b>' + label_text + '</b></big>')
		label.set_alignment(0, 0)
		dialog.vbox.pack_start(label, False, padding=2)

		separator = gtk.HSeparator()
		dialog.vbox.pack_start(separator, False, padding = 2)

		elem_notebook = ElementNotebook(self.xml_node, False)
		elem_notebook.update(self.xml_node)
		dialog.vbox.pack_start(elem_notebook.widget, True, padding = 5)
		dialog.vbox.pack_start(elem_notebook.bbox, False, padding = 2)

		dialog.vbox.show_all()

		if self.obj_type not in ["primitive", "template"] and add_prompt :
			if rsc_id != "" :
				title_suffix = _("Sub-resource For \"%s\"")%rsc_id
			else :
				title_suffix = _("Sub-resource")

			first_title = title + " - " + _("Add ") + title_suffix
			later_title = title + " - " + _("Continue Adding ") + title_suffix
			append_title = first_title

			while True :
				if elem_notebook.on_add(invoked_by_wizard = True, append_title = append_title) == 0 :
					break
				#if self.obj_type in ["clone", "master"] :
				#	break
				append_title = later_title

		if self.obj_type == "primitive" :
			set_page_type = "instance_attributes"
		elif self.obj_type == "group" :
			set_page_type = "primitive"
		else :
			if len(self.xml_node.getElementsByTagName("group")) > 0 :
				set_page_type = "group"
			else :
				set_page_type = "primitive"

		elem_notebook.restore_status((set_page_type, None, {}))
		#elem_notebook.on_after_show()

		save_top_window = top_window
		top_window = dialog

		while True :
			ret = dialog.run()

			if ret == gtk.RESPONSE_APPLY :
				dialog.destroy()
				top_window = save_top_window
				return self.xml_node
			elif ret == gtk.RESPONSE_REJECT :
				dialog.destroy()
				top_window = save_top_window
				return self.first_page_update_run()
			else :
				dialog.destroy()
				top_window = save_top_window
				return None

	def run(self) :
		if self.current_page == None :
			ret = self.first_page_init_run()
		elif self.current_page == 0 :
			ret = self.first_page_update_run()
		else :
			ret = self.last_page()

		return ret

	def destroy(self) :
		#global top_window
		#self.dialog.destroy()
		#top_window = self.save_top_window
		pass

class ObjectViewDlg :
	def __init__(self, xml_node, is_newobj = False) :
		self.xml_node = xml_node

		global top_window

		if is_newobj :
			title_prefix = _("Add")
		else :
			title_prefix = _("Edit")

		title = title_prefix + " " + _(name_cap(xml_node.tagName))
		dialog = gtk.Dialog(title, top_window, gtk.DIALOG_MODAL,
			(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, str(_("Reset")), gtk.RESPONSE_APPLY, gtk.STOCK_OK, gtk.RESPONSE_OK))
		dialog.set_border_width(5)
		dialog.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_NORMAL)
		dialog.set_default_response(gtk.RESPONSE_OK)
		self.dialog = dialog

		obj_view = ObjectView(self.xml_node, is_newobj, self.on_changed)
		self.obj_view = obj_view
		dialog.vbox.pack_start(obj_view.widget)
		dialog.vbox.show()
		dialog.set_response_sensitive(gtk.RESPONSE_APPLY, False)

		self.save_top_window = top_window
		top_window = dialog

	def run(self) :
		while True :
			ret = self.dialog.run()
			if ret in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT] :
				self.obj_view.reset()
				self.destroy()
				return None
			elif ret == gtk.RESPONSE_APPLY :
				self.on_reset()
			else :
				passed = self.obj_view.validate()
				if passed :
					return self.obj_view.xml_node

	def destroy(self) :
		global top_window
		self.dialog.destroy()
		top_window = self.save_top_window

	def on_changed(self) :
		self.dialog.set_response_sensitive(gtk.RESPONSE_APPLY, True)

	def on_reset(self) :
		ret = confirmbox(top_window, _("This will reset the current object attributes and all sub-objects to the initial configurations."),
				(gtk.STOCK_NO, gtk.RESPONSE_NO, gtk.STOCK_YES, gtk.RESPONSE_YES),
				_("Reset the configurations?"))
		if ret == gtk.RESPONSE_YES :
			self.obj_view.reset()
			self.obj_view.update()
			self.dialog.set_response_sensitive(gtk.RESPONSE_APPLY, False)

class TransitionInfoDlg :
	def __init__(self) :
		global top_window
		self.G = None
		dialog = gtk.Dialog(_("Transition Information"), top_window, gtk.DIALOG_MODAL,
			(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE, 
			gtk.STOCK_SAVE, gtk.RESPONSE_APPLY))
			#(gtk.STOCK_HELP, gtk.RESPONSE_HELP, gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE, 
			#gtk.STOCK_SAVE, gtk.RESPONSE_APPLY))
		dialog.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_NORMAL)
		dialog.set_default_size(750, 550)
 
		vbox = gtk.VBox()
		label = gtk.Label(_("Transition") + _(":"))
		label.set_alignment(0, 0.5)
		vbox.pack_start(label, False, padding=2)

		self.live_radio_btn = gtk.RadioButton(None, _("Live"))
		self.live_radio_btn.set_alignment(0.1, 0.5)
		self.live_radio_btn.set_active(True)
		vbox.pack_start(self.live_radio_btn, False, padding=2)

		hbox = gtk.HBox()
		history_radio_btn = gtk.RadioButton(self.live_radio_btn, _("History") + _(":"))
		history_radio_btn.set_alignment(0.1, 0.5)
		hbox.pack_start(history_radio_btn, False, padding=2)

		self.search_btn = gtk.Button(stock=gtk.STOCK_FIND)
		self.search_btn.set_sensitive(False)
		hbox.pack_start(self.search_btn, False, padding=2)

		store = gtk.ListStore(str, str)
		self.combo_entry = gtk.ComboBoxEntry(store)
		cell = gtk.CellRendererText()
		self.combo_entry.pack_start(cell, True)
		self.combo_entry.set_sensitive(False)
		self.combo_entry.add_attribute(cell, 'text', 1)
		hbox.pack_start(self.combo_entry, False, padding=2)

		self.refresh_btn = gtk.Button(stock=gtk.STOCK_REFRESH)
		self.refresh_btn.set_alignment(0.1, 0.5)
		hbox.pack_start(self.refresh_btn, False, padding=2)
		vbox.pack_start(hbox,False,padding=5)

		dialog.vbox.pack_start(vbox, False, padding=2)

		self.summary_label = gtk.Label()
		self.summary_label.set_alignment(0, 0.5)
		dialog.vbox.pack_start(self.summary_label, False, padding=5)

		notebook = gtk.Notebook()
		dialog.vbox.pack_start(notebook, True)
		self.notebook = notebook

		vbox = gtk.VBox()
		tab_label = gtk.Label(_("Graph"))
		notebook.append_page(vbox, tab_label)

		sw = gtk.ScrolledWindow()
		sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		vbox.pack_start(sw, True)

		self.image = gtk.Image()
		sw.add_with_viewport(self.image)

		vbox = gtk.VBox()
		tab_label = gtk.Label(_("Detail"))
		notebook.append_page(vbox, tab_label)

		hbox = gtk.HBox()
		label = gtk.Label(_("Verbosity") + _(":"))
		hbox.pack_start(label, False, padding=2)

		default_verbosity = 0
                adj = gtk.Adjustment(default_verbosity, 0, 99, 1, 5)
		self.detail_spin_btn = gtk.SpinButton(adj, 0, 0)
		self.detail_spin_btn.set_width_chars(2)
		self.detail_spin_btn.set_wrap(True)
		hbox.pack_start(self.detail_spin_btn, False, padding=2)

		self.detail_refresh_btn = gtk.Button(stock=gtk.STOCK_REFRESH)
		hbox.pack_start(self.detail_refresh_btn, False, padding=2)

		vbox.pack_start(hbox, False, padding=2)

		sw = gtk.ScrolledWindow()
		sw.set_shadow_type(gtk.SHADOW_IN)
		sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		vbox.pack_start(sw, True)

		self.pe_detail_text = gtk.TextView()
		#self.pe_detail_text.set_wrap_mode(gtk.WRAP_WORD)
		self.pe_detail_text.set_property("editable", False)
		self.pe_detail_textbuffer = self.pe_detail_text.get_buffer()
		sw.add(self.pe_detail_text)

		vbox = gtk.VBox()
		tab_label = gtk.Label(_("Scores"))
		notebook.append_page(vbox, tab_label)

		sw = gtk.ScrolledWindow()
		sw.set_shadow_type(gtk.SHADOW_IN)
		sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		vbox.pack_start(sw, True)

		self.pe_scores_text = gtk.TextView()
		#self.pe_scores_text.set_wrap_mode(gtk.WRAP_WORD)
		self.pe_scores_text.set_property("editable", False)
		self.pe_scores_textbuffer = self.pe_scores_text.get_buffer()
		sw.add(self.pe_scores_text)

		self.live_radio_btn.connect("activate", self.on_refresh)
		history_radio_btn.connect("toggled", self.on_radio_changed)
		history_radio_btn.connect("activate", self.on_refresh)
		self.search_btn.connect("clicked", self.on_search)
		self.combo_entry.connect("changed", self.on_value_changed)
		self.combo_entry.child.connect("activate", self.on_refresh)
		self.refresh_btn.connect("clicked", self.on_refresh)
		self.detail_spin_btn.connect("value-changed", self.on_detail_value_changed)
		self.detail_refresh_btn.connect("clicked", self.on_detail_refresh)

		self.on_refresh()

		dialog.show_all()

		if not support_gv :
			notebook.get_nth_page(0).hide_all()

		save_top_window = top_window
		top_window = dialog

		while True :
			ret = dialog.run()
			if ret == gtk.RESPONSE_APPLY :
				self.save_transition_info()
			#elif ret == gtk.RESPONSE_HELP :
			#	self.show_help()
			else :
				break

		if support_gv and self.G != None :
			gv.rm(self.G)

		dialog.destroy()
		top_window = save_top_window

	def on_radio_changed(self, radio_btn) :
		radio_active = radio_btn.get_active()
		self.search_btn.set_sensitive(radio_active)
		self.combo_entry.set_sensitive(radio_active)

		self.refresh_btn.set_sensitive(True)

	def on_value_changed(self, combo_entry) :
		self.refresh_btn.set_sensitive(True)

	def on_search(self, search_btn) :
		rpdlg = TimeFrameDlg()
		pe_params = rpdlg.set_params(_("Transitions"), (True, True, True, False))
		if pe_params == None :
			return

		if pe_params.get("ftime") != None :
			pe_params["ftime"] = int(time.mktime(pe_params["ftime"]))
		if pe_params.get("ttime") != None :
			pe_params["ttime"] = int(time.mktime(pe_params["ttime"]))

		input_info_list = self.get_pe_inputs(pe_params.get("ftime", ""), pe_params.get("ttime", ""))
		if input_info_list == None :
			return

		show_len = 30
		late_len = 27
		early_len = show_len - late_len

		store = gtk.ListStore(str, str)
		if len(input_info_list) > show_len :
			for input_info in input_info_list[:late_len] :
				store.append(input_info)
			omit_len = len(input_info_list) - show_len
			store.append(["", _("[Omitted %d transitions...]")%omit_len])
			for input_info in input_info_list[-early_len:] :
				store.append(input_info)
		else :
			for input_info in input_info_list :
				store.append(input_info)
		self.combo_entry.set_model(store)

	def get_pe_inputs(self, ftime, ttime) :
		cmd = "get_pe_inputs\n%s\n%s"%(ftime, ttime)

		input_info = window.do_cmd_with_pbar(cmd, _("Transitions"),
				_("Searching the transitions may take a while,") + "\n"
				+ _("depending on the number of transitions..."),
				_("Cannot find any transition record"))

		if input_info == None :
			return None

		input_dict = {}
		for i in range(len(input_info)) :
			input_list = input_info[i].split()
			j = 0
			while j < len(input_list) :
				time_stamp = float(input_list[j+1])
				if not input_dict.has_key(time_stamp) :
					input_dict[time_stamp] = []
				input_dict[time_stamp].append(input_list[j])
				j += 2

		input_time_list = input_dict.keys()
		input_time_list.sort(reverse = True)

		input_info_list = []
		for i in range(len(input_time_list)) :
			input_time = input_time_list[i]

			input_files = input_dict[input_time]
			input_files.sort()
			for input_file in input_files :
				input_id = os.path.splitext(input_file)[0]
				info_text = time.ctime(input_time)
				input_info_list.append([input_id, info_text])

		return input_info_list

	def on_detail_value_changed(self, spin_btn) :
		self.detail_refresh_btn.set_sensitive(True)

	def on_refresh(self, btn=None) :
		pe_input = self.get_pe_input_id()
		if pe_input == None :
			return

		pe_summary = manager.do_cmd("get_pe_summary\n%s\n%s"%(pe_input[0], pe_input[1]))
		if pe_summary == None or len(pe_summary) < 1 :
			msgbox(top_window, _("The specified transition doesn't exist"))
			return

		if pe_input[0] == "live" :
			label_text = "Live"
		else :
			label_text = "-".join(pe_input)

		time_str = time.ctime(float(pe_summary[0]))
		label_text +=  "  (" + time_str + ")"
		self.summary_label.set_markup('<b>' + label_text + '</b>')

		self.show_pe_graph(pe_input)
		self.show_pe_detail(pe_input)
		self.show_pe_scores(pe_input)
		self.refresh_btn.set_sensitive(False)
		self.detail_refresh_btn.set_sensitive(False)

	def on_detail_refresh(self, btn=None) :
		pe_input = self.get_pe_input_id_label()
		if pe_input == None :
			return

		self.show_pe_detail(pe_input)
		self.detail_refresh_btn.set_sensitive(False)

	def get_pe_input_id(self) :
		if self.live_radio_btn.get_active() :
			pe_input = ("live", "")
		else :
			pe_series = ["error", "warn", "input"]
			error_str = _("Please specify a proper identity of a transition") + _(".") + "\n" \
					+ _("Such as") + _(":")  \
					+ "\"pe-error-100\", \"warn-36\", \"input 62\", \"pe-error-45.bz2\"..." + "\n" \
					+ _("Transition type: \"error\", \"warn\" or \"input\"")
			pe_str = self.combo_entry.child.get_text()
			if len(pe_str) == 0 :
				msgbox(top_window, error_str)
				return None
				
			pe_str_lower = pe_str.lower()
			for pe_type in pe_series :
				if pe_str_lower.count(pe_type) :
					break
			else :
				msgbox(top_window, error_str)
				return None

			pe_num = extract_int(pe_str)
			if pe_num == None :
				msgbox(top_window, error_str)
				return None

			pe_input = ("pe-" + pe_type, pe_num)

		return pe_input

	def get_pe_input_id_label(self) :
		summary_text = self.summary_label.get_text()
		pe_input_id = summary_text.split("(")[0].rstrip()
		if pe_input_id == "Live" :
			pe_input = ("live", "")
		elif pe_input_id.startswith("pe-") :
			id_split = pe_input_id.split("-")
			if len(id_split) == 3 :
				pe_input = (id_split[0] + "-" + id_split[1], id_split[2])
			else :
				pe_input = None
		else :
			pe_input = None

		return pe_input

	def show_pe_graph(self, pe_input) :
		if not support_gv :
			return

		if self.G != None :
			gv.rm(self.G)
			self.G = None
		self.image.clear()
		graph_str = self.gen_pe_graph(pe_input)
		if graph_str != None :
			G = gv.readstring(graph_str)
			gv.layout(G, "dot")
			try :
				(fd, tmp_png) = tempfile.mkstemp(suffix=".png")
			except IOError, msg :
				msgbox(top_window, _("I/O error") + _(": ") + str(msg))
				return
			os.close(fd)
			gv.render(G, "png", tmp_png)
			self.G = G
			self.image.set_from_file(tmp_png)
			os.unlink(tmp_png)
		self.graph_str = graph_str

	def gen_pe_graph(self, pe_input) :
		cmd = "gen_pe_graph\n%s\n%s"%(pe_input[0], pe_input[1])
		graph_lines = window.do_cmd_with_pbar(cmd, _("Transition Graph"),
				_("Generating the transition graph may take a while..."),
				_("Failed to generate the transition graph"))
		if graph_lines == None :
			return None

		graph_str = "\n".join(graph_lines)
		return graph_str

	def show_pe_detail(self, pe_input) :
		verbosity = int(self.detail_spin_btn.get_value())

		self.pe_detail_textbuffer.set_text("")

		cmd = "gen_pe_info\n%s\n%s\n%s"%(pe_input[0], pe_input[1], verbosity)
		detail_lines = window.do_cmd_with_pbar(cmd, _("Transition Detail"),
				_("Generating the transition detail may take a while..."),
				_("Failed to generate the transition detail"))
		if detail_lines == None :
			return

		detail_str = "\n".join(detail_lines)

		self.pe_detail_textbuffer.set_text(detail_str)

	def show_pe_scores(self, pe_input) :
		self.pe_scores_textbuffer.set_text("")

		cmd = "gen_pe_info\n%s\n%s\nscores"%(pe_input[0], pe_input[1])
		scores_lines = window.do_cmd_with_pbar(cmd, _("Transition Scores"),
				_("Generating the transition scores may take a while..."),
				_("Failed to generate the transition scores"))
		if scores_lines == None :
			return
		scores_str = "\n".join(scores_lines)

		self.pe_scores_textbuffer.set_text(scores_str)

	def save_transition_info(self) :
		page_num = self.notebook.get_current_page()
		if page_num == 0 :
			if not support_gv :
				msgbox(top_window, _("Cannot save the graph for specified transition"))
				return
			default_name = "pe-graph.png"
			filter_list = ((_("PNG Image"), ("*.png",)),
					(_("JPEG Image"), ("*.jpg", "*.jpeg", "*.jpe")),
					(_("GIF Image"), ("*.gif",)),
					(_("TIFF Image"), ("*.tiff", "*.tif")),
					(_("Dot File"), ("*.dot",)),
					)
		elif page_num == 1 :
			default_name = "pe-detail"
			filter_list = None
		else:
			default_name = "pe-scores"
			filter_list = None

		sfdlg = SelectFileDlg()
		(save_file, save_type) = sfdlg.select_file(default_name, filter_list)
		if save_file == None :
			return

		save_str = None
		if page_num == 0 :
			for (filter_name, filter_pattern) in filter_list :
				if filter_name == save_type :
					format = filter_pattern[0][2:]
					if format != "dot" :
						gv.render(self.G, format, save_file)
						return
					else :
						save_str = self.graph_str
					break
		elif page_num == 1 :
			save_str = self.pe_detail_textbuffer.get_text(*self.pe_detail_textbuffer.get_bounds())
		else :
			save_str = self.pe_scores_textbuffer.get_text(*self.pe_scores_textbuffer.get_bounds())

		if save_str == None :
			msgbox(top_window, _("Cannot save the information for specified transition"))
			return

		try :
			fd = os.open(save_file, os.O_RDWR|os.O_CREAT|os.O_TRUNC, 0644)
		except OSError, msg :
			msgbox(top_window, _("System error") + _(": ") + str(msg))
			return

		try :
			os.write(fd, save_str)
		except OSError, msg :
			msgbox(top_window, _("System error") + _(": ") + str(msg))
			os.close(fd)
			return
		os.close(fd)

	def show_help(self) :
		global top_window

		help_str = _("""Interpreting the graph:
* Arrows indicate ordering dependancies
* Dashed-arrows indicate dependancies that are not present in the transition graph
* Actions with a dashed border of any color do not form part of the transition graph
* Actions with a green border form part of the transition graph
* Actions with a red border are ones the cluster would like to execute but are unrunnable
* Actions with a blue border are ones the cluster does not feel need to be executed
* Actions with orange text are pseudo/pretend actions that the cluster uses to simplify the graph
* Actions with black text are sent to the LRM
* Resource actions have text of the form {rsc}_{action}_{interval} {node}
* Any action depending on an action with a red border will not be able to execute.
* Loops are really bad. Please report them to the development team.""")

		dialog = gtk.Dialog("Help", top_window, gtk.DIALOG_MODAL,
				(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE))
		dialog.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_NORMAL)
		dialog.set_size_request(590, 270)
		dialog.set_default_response(gtk.RESPONSE_CLOSE)

		sw = gtk.ScrolledWindow()
		sw.set_shadow_type(gtk.SHADOW_IN)
		sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		dialog.vbox.pack_start(sw, True)

		help_text = gtk.TextView()
		#help_text.set_wrap_mode(gtk.WRAP_WORD)
		help_text.set_property("editable", False)
		help_textbuffer = help_text.get_buffer()
		help_textbuffer.set_text(help_str)
		sw.add(help_text)

		dialog.show_all()
		save_top_window = top_window
		top_window = dialog

		dialog.run()
		dialog.destroy()
		top_window = save_top_window

class TimeFrameDlg :
	def set_params(self, title, (from_chkbtn, from_sensitive, to_chkbtn, to_sensitive)) :
		global top_window
		dialog = gtk.Dialog(title, top_window, gtk.DIALOG_MODAL,
			(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK))
		dialog.set_border_width(5)
		dialog.set_default_response(gtk.RESPONSE_OK)
		self.dialog = dialog

		current_time = time.time()
		from_time = time.localtime(current_time - 1800)
		to_time = time.localtime(current_time)

		fdatetime = self.render_time_widgets("<b>"+_("From")+"</b>", from_time, from_chkbtn, from_sensitive)
		tdatetime = self.render_time_widgets("<b>"+_("To")+"</b>", to_time, to_chkbtn, to_sensitive)

		save_top_window = top_window
		top_window = dialog
		dialog.show_all()

		while True :
			ret = dialog.run()
			if ret in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT] :
				top_window = save_top_window
				dialog.destroy()
				return None
			else :
				if fdatetime.time_hbox.get_property("sensitive") :
					ftime = fdatetime.get_time() 
				else :
					ftime = None

				if tdatetime.time_hbox.get_property("sensitive") :
					ttime = tdatetime.get_time()
				else :
					ttime = None

				passed = True
				if ftime != None and ttime != None and time.mktime(ftime) > time.mktime(ttime) :
					msgbox(top_window, _("The \"From\" time should before the \"To\" one"))
					passed = False

				if passed :
					params = {}
					if ftime != None :
						params["ftime"] = ftime
					if ttime != None :
						params["ttime"] = ttime

					top_window = save_top_window
					dialog.destroy()
					return params

	def render_time_widgets(self, label, default_time, chkbtn, sensitive) :
		time_label = gtk.Label()
		time_label.set_markup(_(label))
		time_label.set_alignment(0, 0.5)
		
		datetime = DateTime(default_time)

		if chkbtn :
			time_checkbutton = gtk.CheckButton()
			time_checkbutton.add(time_label)
			if sensitive :
				time_checkbutton.set_active(True)
			time_checkbutton.connect("toggled", self.on_checkbutton_toggled, datetime.time_hbox)
			self.dialog.vbox.pack_start(time_checkbutton, False, padding=2)
		else :
			self.dialog.vbox.pack_start(time_label, False, padding=2)

		datetime.time_hbox.set_sensitive(sensitive)
		self.dialog.vbox.pack_start(datetime.time_hbox, False, padding=2)

		return datetime

	def on_checkbutton_toggled(self, widget, hbox) :
		hbox.set_sensitive(widget.get_active())

class SelectFileDlg :
	def select_file(self, orig_filename = None, filter_list = None) :
		global top_window
		file_dialog = gtk.FileChooserDialog(_("Save as ..."), None, 
				gtk.FILE_CHOOSER_ACTION_SAVE,
				(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
				gtk.STOCK_SAVE, gtk.RESPONSE_OK))
		if orig_filename != None :
			file_dialog.set_current_name(orig_filename)

		save_top_window = top_window
		top_window = file_dialog

		if filter_list != None :
			for (filter_name, filter_patterns) in filter_list :
				filter = gtk.FileFilter()
				filter.set_name(filter_name)
				for filter_pattern in filter_patterns :
					filter.add_pattern(filter_pattern)
				file_dialog.add_filter(filter)

		while True :
			ret = file_dialog.run()
			if ret in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT] :
				top_window = save_top_window
				file_dialog.destroy()
				return (None, None)
			else :
				save_folder = file_dialog.get_current_folder()
				save_file = file_dialog.get_filename()
				passed = True
				try :
					if not os.access(save_folder, os.R_OK | os.W_OK | os.X_OK) :
						msgbox(top_window, _("Permission denied") + (": ") + save_folder)
						passed = False
						continue
					if os.access(save_file, os.F_OK) :
						retval = confirmbox(top_window, _("A file with the same name already exists") +_(": ")
								+ os.path.basename(save_file) + "\n"
								+_("Do you want to overwrite it?"),
								(gtk.STOCK_NO, gtk.RESPONSE_NO,
								gtk.STOCK_YES, gtk.RESPONSE_YES),
								_("Replace it?"))
						if retval in [gtk.RESPONSE_NO, gtk.RESPONSE_DELETE_EVENT] :
							passed = False
							continue
							
				except OSError, msg :
					msgbox(top_window, _("System error") + _(": ") + str(msg))
					passed = False

				if passed :
					top_window = save_top_window
					if filter_list != None :
						save_type = file_dialog.get_filter().get_name()
					else :
						save_type = None
					file_dialog.destroy()
					return (save_file, save_type)

class DateTime:
	def __init__(self, default_time) :
		time_hbox = gtk.HBox()

		time_date = gtk.Entry()
		time_date.set_width_chars(10)
		time_date.set_editable(False)
		time_date.set_activates_default(True)
		time_hbox.pack_start(time_date, False)

		time_cal_window = gtk.Window(gtk.WINDOW_POPUP)
		time_cal = gtk.Calendar()
		time_cal_window.add(time_cal)
		
		time_cal_button = gtk.ToggleButton()
		arrow = gtk.Arrow(gtk.ARROW_DOWN, gtk.SHADOW_OUT)
		time_cal_button.add(arrow)
		time_cal_button.connect("toggled", self.on_toggled, time_cal_window)
		time_hbox.pack_start(time_cal_button, False)

		time_cal_window.connect("button-press-event", self.on_button_press, time_cal_button)
		time_cal_window.connect("key-press-event", self.on_key_press, time_cal_button)

		time_cal.connect("day-selected", self.on_day_selected, time_date)

		time_cal.select_month(default_time[1]-1, default_time[0])
		time_cal.select_day(default_time[2])

		space = gtk.Label(" ")
		time_hbox.pack_start(space, False)

		time_hr_adj = gtk.Adjustment(default_time[3], 00, 23, 1, 4)
		time_hr = gtk.SpinButton(time_hr_adj, 0, 0)
		time_hr.set_width_chars(2)
		time_hr.set_wrap(True)
		time_hbox.pack_start(time_hr, False)

		time_hrcolon = gtk.Label(":")
		time_hbox.pack_start(time_hrcolon, False)

		time_min_adj = gtk.Adjustment(default_time[4], 00, 59, 1, 5)
		time_min = gtk.SpinButton(time_min_adj, 0, 0)
		time_min.set_width_chars(2)
		time_min.set_wrap(True)
		time_hbox.pack_start(time_min, False)
		
		time_mincolon = gtk.Label(":")
		time_hbox.pack_start(time_mincolon, False)

		time_sec_adj = gtk.Adjustment(default_time[5], 00, 59, 1, 5)
		time_sec = gtk.SpinButton(time_sec_adj, 0, 0)
		time_sec.set_width_chars(2)
		time_sec.set_wrap(True)
		time_hbox.pack_start(time_sec, False)

		time_widgets = {}
		self.time_date = time_date
		self.time_hr = time_hr
		self.time_min = time_min
		self.time_sec = time_sec
		self.time_hbox = time_hbox
		self.time_hrcolon = time_hrcolon
		self.time_mincolon = time_mincolon

	def on_toggled(self, widget, cal_window) :
		if widget.get_active() :
			self.cal_popup(widget, cal_window)
		else :
			self.cal_hide(widget, cal_window)

	def cal_popup(self, widget, cal_window) :
		(x, y) = widget.get_parent_window().get_position()
		x += widget.allocation.x
		y += widget.allocation.y + widget.allocation.height
		cal_window.grab_add()
		cal_window.move(x, y)
		cal_window.grab_focus()
		cal_window.show_all()

		if gtk.gdk.pointer_grab(cal_window.window, True,
			gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK | gtk.gdk.POINTER_MOTION_MASK,
			None, None, 0L) == gtk.gdk.GRAB_SUCCESS :
			if (gtk.gdk.keyboard_grab (cal_window.window, True, 0L) != 0):
				gtk.gdk.pointer_ungrab(0L)

	def cal_hide(self, widget, cal_window) :
		cal_window.hide()
		cal_window.grab_remove()
		gtk.gdk.pointer_ungrab(0L)
		gtk.gdk.keyboard_ungrab(0L)

	def on_button_press(self, cal_window, event, button) :
		button.set_active(False)
				
	def on_key_press(self, cal_window, event, button) :
		if event.keyval == gtk.keysyms.Escape :
			button.set_active(False)
		else :
			gtk.gdk.keyboard_grab (cal_window.window, True, 0L)

	def on_day_selected(self, cal_window, date_entry) :
		(year, month, day) = cal_window.get_date()
		mytime = time.mktime((year, month+1, day, 0, 0, 0, 0, 0, -1))
		localtime = time.strftime("%Y-%m-%d", time.localtime(mytime))
		date_entry.set_text(localtime)
		#date_entry.set_text("%d-%02d-%02d"%(year, month+1, day))

	def get_time(self) :
		datetime = time.strptime("%s %02d:%02d:%02d"%(self.time_date.get_text(),
							self.time_hr.get_value(),
							self.time_min.get_value(),
							self.time_sec.get_value()), "%Y-%m-%d %H:%M:%S")
		return datetime
	def get_date(self) :
                date_struct =time.strptime("%s"%(self.time_date.get_text()),"%Y-%m-%d",)
		date = time.strftime("%Y-%m-%d",date_struct)
		return date


class ProgressPulse :
	def __init__(self, title, msg, pulse_msg, button=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL), destroy_condition = None) :
		global top_window
		self.destroy_condition = destroy_condition

		dialog = gtk.Dialog(title, top_window, gtk.DIALOG_MODAL, button)
		dialog.set_border_width(5)
		if msg != None :
			label = gtk.Label(msg)
			dialog.vbox.pack_start(label, False, padding=2)
		self.pbar = gtk.ProgressBar()
		if pulse_msg != None :
			self.pbar.set_text(pulse_msg)
		self.timer = gobject.timeout_add(100, self.pulse)
		dialog.vbox.pack_start(self.pbar, False, padding=2)
		dialog.show_all()

		self.save_top_window = top_window
		self.dialog = dialog

	def pulse(self) :
		if self.destroy_condition != None and self.destroy_condition() :
			self.destroy()
			return False
		else :
			self.pbar.pulse()
			return True

	def destroy(self) :
		global top_window
		top_window = self.save_top_window
		self.dialog.destroy()
		gobject.source_remove(self.timer)

	def run(self) :	
		ret = self.dialog.run()
		self.destroy()
		return ret

class DesReportDlg:
	def __init__(self, des_file_lines) :
		global top_window
		self.des_file_lines = des_file_lines

		dialog = gtk.Dialog(_("Description of Cluster Report"), top_window, gtk.DIALOG_MODAL,
				(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK))
		dialog.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_NORMAL)
		dialog.set_border_width(5)

		entries = {}
		combo_entries = {}
		name_labels = []

		for line in des_file_lines :
			if line.startswith("Severity: [choose one] ") :
				options =  line.replace("Severity: [choose one] ", "").split()
				hbox = gtk.HBox()
				label = gtk.Label(_("Severity") + _(":"))
				label.set_alignment(0, 0.5)
				hbox.pack_start(label, False)
				name_labels.append(label)
				
				combo_entry = gtk.combo_box_entry_new_text()
				combo_entry.append_text("")
				for option in options :
					combo_entry.append_text(option)
				hbox.pack_start(combo_entry)
				dialog.vbox.pack_start(hbox, False, padding=1)
				combo_entries["severity"] = combo_entry 
			elif line.startswith("Component: [choose one] ") :
				options = line.replace("Component: [choose one] ", "").split()
				hbox = gtk.HBox()
				label = gtk.Label(_("Component") + _(":"))
				label.set_alignment(0, 0.5)
				hbox.pack_start(label, False)
				name_labels.append(label)
				
				combo_entry = gtk.combo_box_entry_new_text()
				combo_entry.append_text("")
				for option in options :
					combo_entry.append_text(option)
				hbox.pack_start(combo_entry)
				dialog.vbox.pack_start(hbox, False, padding=1)
				combo_entries["component"] = combo_entry
			elif line.startswith("Subject:") :
				hbox = gtk.HBox()
				label = gtk.Label(_("Subject") + _(":"))
				label.set_alignment(0, 0.5)
				name_labels.append(label)
				hbox.pack_start(label, False)
				entry = gtk.Entry()
				hbox.pack_start(entry)
				dialog.vbox.pack_start(hbox, False, padding=1)
				entries["subject"] = entry
			elif line.startswith("Detailed description:") :
				label = gtk.Label(_("Detailed description") + _(":"))
				label.set_alignment(0, 0.5)
				dialog.vbox.pack_start(label, False, padding=1)

				sw = gtk.ScrolledWindow()
				sw.set_shadow_type(gtk.SHADOW_IN)
				sw.set_border_width(5)
				sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
				des_text = gtk.TextView()
				des_text.set_wrap_mode(gtk.WRAP_WORD)
				self.des_textbuffer = des_text.get_buffer()
				sw.add(des_text)
				dialog.vbox.pack_start(sw, padding=1)
			elif line.startswith("System info") :
				break
			elif line.startswith("Common system info found") :
				break
			elif not line.startswith("[...]") and not line.startswith("---") :
				if len(line) > 1:
					if line.startswith("Date:"):
						label = gtk.Label(_("Date:") + line.replace("\n", "").replace("Date:", ""))
					elif line.startswith("By:"):
						label = gtk.Label(_("By:") + line.replace("\n", "").replace("By:", ""))
					else:
						label = gtk.Label(_(line.replace("\n", "")))
				else:
					label = gtk.Label(line.replace("\n", ""))
				label.set_alignment(0, 0.5)
				label.set_line_wrap(True)
				label.set_selectable(True)
				dialog.vbox.pack_start(label, False, padding=1)

		name_label_max_len = 0
		for name_label in name_labels :
			name_label_len = name_label.size_request()[0]
			if name_label_len >  name_label_max_len :
				name_label_max_len = name_label_len
		for name_label in name_labels :
			name_label.set_size_request(name_label_max_len, -1)

		widgets = {}
		widgets["entries"] = entries
		widgets["combo_entries"] = combo_entries
		self.widget_group = WidgetGroup(widgets)

		dialog.show_all()
		self.dialog = dialog
		self.save_top_window = top_window

	def run(self) :
		global top_window
		des_file_lines  = self.des_file_lines
		ret = self.dialog.run()
		if ret in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT] :
			top_window = self.save_top_window
			self.dialog.destroy()
			return None
		else :
			fields = self.widget_group.get_values()
			detailed_des = self.des_textbuffer.get_text(*self.des_textbuffer.get_bounds())
			new_file_lines = []
			for i in range(len(des_file_lines)) :
				if des_file_lines[i].startswith("Severity: [choose one] ") :
					des_file_lines[i] = "Severity: %s\n"%fields.get("severity", "")
				elif des_file_lines[i].startswith("Component: [choose one] ") :
					des_file_lines[i] = "Component: %s\n"%fields.get("component", "")
				elif des_file_lines[i].startswith("Subject:") :
					des_file_lines[i] = "Subject: %s\n"%fields.get("subject", "")
				elif des_file_lines[i-2].startswith("Detailed description:") :
					des_file_lines[i] = detailed_des + "\n"
			top_window = self.save_top_window
			self.dialog.destroy()
			return des_file_lines 

class MainWindow :
	'''
	Main UI window to show information to user and get users input
	'''
	win_widget = None
	actiongroup = None
	uimanager = None
	cur_type = None
	cur_status = None
	cur_name = None
	cur_view = None
	statusbar = None
	view_status = {}
	
	# utility functions
	def set_action_sensitive(self, action, sensitive) :
		if self.actiongroup.get_action(action) != None :
			self.actiongroup.get_action(action).set_property("sensitive", sensitive)
		elif self.radio_tool_action_group.get_action(action) != None :
			self.radio_tool_action_group.get_action(action).set_property("sensitive", sensitive)
		elif self.toggle_tool_action_group.get_action(action) != None :
			self.toggle_tool_action_group.get_action(action).set_property("sensitive", sensitive)

	# system event handler
	def on_delete_event(self, widget, event, data=None) :
		self.do_quit(None)
		return False
	
	def update_ui(self) :
		dc = manager.get_dc()
		if dc == [] or dc == None:
			have_dc = False
		else:
			have_dc = True

		self.set_action_sensitive('logout',manager.connected)
		self.set_action_sensitive('login',not manager.connected)

		self.set_action_sensitive('transition-info', manager.connected and have_dc)
		self.set_action_sensitive('report', manager.connected and have_dc)

		for action in ["new", "reset", "delete", "commit", "switch"] :
			self.set_action_sensitive(action, manager.connected and have_dc)
		self.set_action_sensitive("diff", manager.connected and have_dc and manager.active_cib != None and manager.active_cib != "")

		#neoshineha ming.liu 
		all_rsc_type = [_("primitive"), _("group"), _("clone"), _("master")]
                self.set_action_sensitive('standby',
                        self.cur_type in ["node"] and have_dc
                        and string.find(self.cur_status, _("standby")) == -1
                        and string.find(self.cur_status, _("never started")) == -1)

                self.set_action_sensitive('active',
                        self.cur_type in ["node"] and have_dc
                        and string.find(self.cur_status, _("standby")) != -1 
                        and string.find(self.cur_status, _("never started")) == -1)

                self.set_action_sensitive('delnode',
                        self.cur_type in ["node"] and have_dc)

                self.set_action_sensitive('cleanuprsc',
                        self.cur_type in all_rsc_type and have_dc)

                self.set_action_sensitive('startrsc',
                        self.cur_type in all_rsc_type and have_dc)

                self.set_action_sensitive('stoprsc',
                        self.cur_type in all_rsc_type and have_dc)

                self.set_action_sensitive('migratersc',
                        self.cur_type in all_rsc_type and have_dc)

                self.set_action_sensitive('managersc',
                        self.cur_type in all_rsc_type and have_dc)

                self.set_action_sensitive('unmanagersc',
                        self.cur_type in all_rsc_type and have_dc)

		self.set_action_sensitive('unmigratersc', manager.connected and have_dc and self.cur_type in all_rsc_type)

                islicflag = HALic_ctrl_IS_flag(manager)
		self.set_action_sensitive('gfs', manager.connected and have_dc) #neoshine add
                self.set_action_sensitive('addrsc',manager.connected and have_dc)

                self.set_action_sensitive('delrsc',
                        manager.connected and have_dc
                        and self.cur_type in [_("primitive"),_("group"),_("clone"),
                                _("location"),_("order"),_("colocation"),_("master")])

		#self.up_btn.set_sensitive(iter != None and model.get_path(iter)[-1] != 0)
                #self.down_btn.set_sensitive(iter != None and model.iter_next(iter) != None)

		(model, iter) = self.maintree.widget.get_selection().get_selected()
                self.set_action_sensitive('uprsc',
                        manager.connected and have_dc and iter != None and model.get_path(iter)[-1] != 0
                        and self.cur_type in [_("primitive"), _("group"), _("clone"), _("master")])

                self.set_action_sensitive('downrsc',
                        manager.connected and have_dc and iter != None and model.iter_next(iter) != None
                        and self.cur_type in [_("primitive"), _("group"), _("clone"), _("master")])
                self.set_action_sensitive('movetogroup', manager.connected and have_dc and self.cur_type in [_("primitive")])
                self.set_action_sensitive('addnodersc', manager.connected and have_dc)
                self.set_action_sensitive('mainnode', manager.connected and have_dc and self.cur_name in manager.get_top_rsc())
                self.set_action_sensitive('addhb', manager.connected and have_dc)
                self.set_action_sensitive('alarm', manager.connected and have_dc)
                self.set_action_sensitive('rscattributes', manager.connected and have_dc and self.cur_type in all_rsc_type)

		try:
                        parent = manager.parent[self.cur_name]
                except:
                        parent = self.cur_name

                self.set_action_sensitive('renamersc', manager.connected and have_dc and self.cur_type in all_rsc_type and (manager.get_rsc_type(parent) not in ["master"]))
                self.set_action_sensitive('globalparameter', manager.connected and have_dc)
                self.set_action_sensitive('logviewer', manager.connected and have_dc)
                self.set_action_sensitive('constraint', manager.connected and have_dc)

                self.set_action_sensitive('addnode', manager.connected and have_dc)
                self.set_action_sensitive('time', manager.connected and have_dc)
                self.set_action_sensitive('diskhb', manager.connected and have_dc)
		self.set_action_sensitive('script-generator', manager.connected and have_dc)
		self.set_action_sensitive('rapid-deploy', manager.connected and have_dc)

                self.set_action_sensitive('refresh', manager.connected and have_dc)
                self.set_action_sensitive('reprobe', manager.connected and have_dc)
                self.set_action_sensitive('maintenance-mode', manager.connected and have_dc)
                self.set_action_sensitive('record-pending', manager.connected and have_dc)
                #self.set_action_sensitive('group-by-node', manager.connected and have_dc)
                self.set_action_sensitive('simple-mode', manager.connected and have_dc)
                self.set_action_sensitive('expert-mode', manager.connected and have_dc)
                self.set_action_sensitive('hack-mode', manager.connected and have_dc)
		#neoshineha end ming.liu
	# functions
	def update(self) :
		self.maintree.update()
		self.statusbar.pop(2)

		window.statusbar.pop(1)
		if manager.connected :
			status_str = _("Connected to ") + manager.username + "@" + manager.server
		else :
			status_str = _("Not connected")
		if mode_level == 0 :
			status_str += " " + _("(") + _("Simple Mode") +_(")")
		elif mode_level == 1 :
			status_str += " " + _("(") + _("Expert Mode") +_(")")
		else :
			status_str += " " + _("(") + _("Hack Mode") +_(")")
		window.statusbar.push(1, status_str)

		self.update_ui()

		return False

	def can_change_view(self) :
		if not self.cur_view.changed :
			return True
		ret = confirmbox(top_window, _("The data of current view have been changed.")+"\n"+_("Apply the changes?"),
			(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
			gtk.STOCK_NO, gtk.RESPONSE_NO,
			gtk.STOCK_YES, gtk.RESPONSE_YES)) 
		if ret == gtk.RESPONSE_YES :
			self.cur_view.on_apply(self.cur_view.widget)
			return True
		if ret == gtk.RESPONSE_NO :
			return True
		return False

	#neoshineha ming.liu
        def on_after_show(self, treeview = None) :
                for child in self.sub_vbox.get_children() :
                        self.sub_vbox.remove(child)
			self.sub_vbox.hide_all()

                if self.cur_type == _("primitive") :
                        self.show_rsc_summary(self.cur_name)
                        self.show_operations(self.cur_name)
                #elif self.cur_type == "resources" :
                #        self.show_sub_attrs(manager.xml_nodes["cib"])
                elif self.cur_type == "node" :
                        for node_state in manager.xml_nodes["cib"].getElementsByTagName("node_state") :
                                if node_state.getAttribute("id") == self.cur_name :
                                        self.show_sub_attrs(node_state)
                                        break

        def show_sub_attrs(self, selected_node) :
                if selected_node == None :
                        return

                if validate_type == "dtd" : 
                        dtd_elem = manager.get_dtd_elem(selected_node.tagName)
                        attr_list = dtd_elem.get_attr_list()
                else :
                        attr_list = []
                        is_any_name = False
                        sorted_rng_nodes = manager.sorted_sub_rng_nodes_by_name(selected_node.tagName)
                        if sorted_rng_nodes != None :
                                attr_rng_nodes = sorted_rng_nodes.get("attribute", [])
                                for rng_node in attr_rng_nodes :
                                        name = rng_node[0][1].getAttribute("name")
                                        if name == "" :
                                                is_any_name = True
                                        elif attr_list.count(name) == 0 :
                                                attr_list.append(name)
                        else :
                                is_any_name = True

                        if is_any_name :
                                for attr_name in  selected_node.attributes.keys() :
                                        if attr_list.count(attr_name) == 0 :
                                                if attr_name == "id" :
                                                        attr_list.insert(0, attr_name)
                                                else :
                                                        attr_list.append(attr_name)

                name_labels = {}
                name_label_max_len = 0
                for attr_name in attr_list :
                        if attr_name in ["admin_epoch", "num_peers", "cib_feature_revision", "remote_access_port",
                                                "ccm_transition", "ignore_dtd", "generated", "crm-debug-origin",
                                                "remote-tls-port", "remote-clear-port", "no-quorum-panic",
                                                "shutdown", "clear_shutdown"] :
                                continue
                        attr_value = selected_node.getAttribute(attr_name)
                        if attr_value == "" or name_labels.get(attr_name) != None :
                                continue
                        hbox = gtk.HBox()
                        name_label = gtk.Label(_(name_cap(attr_name)+":"))
                        name_label.set_alignment(0, 0.5)
                        name_label.set_selectable(True)

                        name_labels[attr_name] = name_label
                        name_label_len = name_label.size_request()[0]
                        if name_label_len > name_label_max_len :
                                name_label_max_len = name_label_len

                        value_label = gtk.Label(attr_value)
                        value_label.set_alignment(0, 0.5)
                        value_label.set_selectable(True)

                        hbox.pack_start(name_label, False, padding=5)
                        hbox.pack_start(value_label, False, padding=5)
                        self.sub_vbox.pack_start(hbox, False, padding=2)

                for name_label in name_labels.values() :
                        name_label.set_size_request(name_label_max_len + 20, -1)

                self.sub_vbox.show_all()

        def get_rsc_failcount(self, rsc_id) :
                rsc_summary = []
                for trans_attr_node in manager.xml_nodes["cib"].getElementsByTagName("transient_attributes") :
                        node_id = trans_attr_node.getAttribute("id")
                        fail_count = ""
                        last_failure = ""
                        for nv_node in trans_attr_node.getElementsByTagName("nvpair") :
                                nv_name = nv_node.getAttribute("name")
                                if nv_name.count("fail-count") and nv_name.count(rsc_id) :
                                        fail_count = nv_node.getAttribute("value")
                                elif nv_name.count("last-failure") and nv_name.count(rsc_id) :
                                        last_failure = nv_node.getAttribute("value")

                        if fail_count == "" :
                                continue

                        summary_str = fail_count
                        node_name = manager.node_name(node_id)
                        if node_name != "" :
                                summary_str += "  (%s, "%node_name
                        else :
                                summary_str += "  (%s, "%node_id

                        if last_failure != "" :
                                last_failure_time = time.ctime(float(last_failure))
                                if len(summary_str) > 0 :
                                        summary_str += "  "
                                summary_str += _("last failure at \"%s\"")%last_failure_time

                        summary_str += ")"

                        rsc_summary.append(summary_str)
                return rsc_summary

        def show_rsc_summary(self, rsc_id) :
                rsc_summary = {}

                (status, mig_threshold) = manager.get_rsc_status(rsc_id)
                if mig_threshold != "0" :
                        rsc_summary["migration-threshold"] = [mig_threshold]

                rsc_summary["fail-count"] = self.get_rsc_failcount(rsc_id)

                name_labels = []
                name_label_max_len = 0
                for attr_name in rsc_summary :
                        for i in range(len(rsc_summary[attr_name])) :
                                hbox = gtk.HBox()
                                if i == 0 :
                                        name_label = gtk.Label(_(name_cap(attr_name)) + _(":"))
                                else :
                                        name_label = gtk.Label("")
                                name_label.set_alignment(0, 0.5)
                                name_label.set_selectable(True)

                                name_labels.append(name_label)
                                name_label_len = name_label.size_request()[0]
                                if name_label_len > name_label_max_len :
                                        name_label_max_len = name_label_len

                                value_label = gtk.Label(rsc_summary[attr_name][i])
                                value_label.set_alignment(0, 0.5)
                                value_label.set_selectable(True)

                                hbox.pack_start(name_label, False, padding=5)
                                hbox.pack_start(value_label, False, padding=5)
                                self.sub_vbox.pack_start(hbox, False, padding=2)

                for name_label in name_labels :
                        name_label.set_size_request(name_label_max_len, -1)

                self.sub_vbox.show_all()

        def show_operations(self, rsc_id) :
                op_fields = ["Call ID", "Operation", "Interval", "Return Code", "Status",
                                "Last Run", "Exec Time", "Queue Time", "Last Return Code Change"]

                store = gtk.TreeStore(*(tuple(str for i in range(len(op_fields)))))
                tree = gtk.TreeView(store)
                for i in range(len(op_fields)) :
                        add_column(tree, _(op_fields[i]), i)

                ops = self.get_operations(rsc_id)
                for node_id in ops :
                        if len(ops[node_id]) == 0 :
                                continue

                        node_name = manager.node_name(node_id)
                        if node_name == "" :
                                node_name = node_id

                        node_root = store.append(None, [node_name, "", "", "", "", "", "", "", ""])
                        call_ids = [call_id for call_id in ops[node_id]]
                        call_ids.sort()
                        for call_id in call_ids :
                                store.append(node_root, ops[node_id][call_id])

                tree.expand_all()

                sw = gtk.ScrolledWindow()
                sw.set_shadow_type(gtk.SHADOW_IN)
                sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
                sw.add(tree)

                self.sub_vbox.pack_start(sw)
                self.sub_vbox.show_all()

        def get_operations(self, rsc_id) :
                if validate_type == "dtd" :
                        call_id_key = "call_id"
                        rc_code_key = "rc_code"
                        op_status_key = "op_status"
                        last_run_key = "last_run"
                        exec_time_key = "exec_time"
                        queue_time_key = "queue_time"
                        last_rc_change_key = "last_rc_change"
                else :
                        call_id_key = "call-id"
                        rc_code_key = "rc-code"
                        op_status_key = "op-status"
                        last_run_key = "last-run"
                        exec_time_key = "exec-time"
                        queue_time_key = "queue-time"
                        last_rc_change_key = "last-rc-change"

                operations = {}
                for lrm_node in manager.xml_nodes["cib"].getElementsByTagName("lrm") :
                        node_id = lrm_node.getAttribute("id")
                        operations[node_id] = {}
                        for lrm_resource_node in lrm_node.getElementsByTagName("lrm_resource") :
                                if lrm_resource_node.getAttribute("id") == rsc_id :
                                        for lrm_rsc_op in lrm_resource_node.getElementsByTagName("lrm_rsc_op") :
                                                operation = lrm_rsc_op.getAttribute("operation")
                                                interval = lrm_rsc_op.getAttribute("interval")
                                                if interval == "0" :
                                                        interval_time = ""
                                                        if operation == "monitor" :
                                                                operation = "probe"
                                                elif interval == "" :
                                                        interval_time = ""
                                                else :
                                                        interval_time = interval+"ms"
                                                rc_code = lrm_rsc_op.getAttribute(rc_code_key)

                                                if rc_code == "7" and operation == "probe" :
                                                        continue
                                                elif operation == "notify" :
                                                        continue

                                                rc_str = manager.lrm_op_rc2str(rc_code)
                                                if rc_code == "" :
                                                        result_str = rc_str
                                                else :
                                                        result_str = "%s (rc=%s)"%(rc_str, rc_code)

                                                call_id = lrm_rsc_op.getAttribute(call_id_key)

                                                op_status = lrm_rsc_op.getAttribute(op_status_key)
                                                op_status_str = manager.op_status2str(op_status)

                                                last_run = lrm_rsc_op.getAttribute(last_run_key)
                                                if last_run != "" :
                                                        last_run_time = time.ctime(float(last_run))
                                                else :
                                                        last_run_time = ""

                                                exec_time = lrm_rsc_op.getAttribute(exec_time_key)
                                                if exec_time == "" :
                                                        exec_time_str = ""
                                                else :
                                                        exec_time_str = exec_time + "ms"

                                                queue_time = lrm_rsc_op.getAttribute(queue_time_key)
                                                if queue_time == "" :
                                                        queue_time_str = ""
                                                else :
                                                        queue_time_str = queue_time + "ms"
                                                last_rc_change = lrm_rsc_op.getAttribute(last_rc_change_key)
                                                if last_rc_change != "" :
                                                        last_rc_change_time = time.ctime(float(last_rc_change))
                                                else :
                                                        last_rc_change_time = ""

                                                operations[node_id][int(call_id)] = [
                                                                                call_id,
                                                                                operation,
                                                                                interval_time,
                                                                                result_str,
                                                                                op_status_str,
                                                                                last_run_time,
                                                                                exec_time_str,
                                                                                queue_time_str,
                                                                                last_rc_change_time
                                                                                ]
                                        break
                return operations

        def judge_node_status(self, node):
                if manager.get_nodetype(node) == 'ping':
                        return -1

                started = manager.get_crm_nodes()
                if node not in started:
                        if manager.get_nodetype(node)=="normal":
                                return 3

                active_nodes = manager.get_active_nodes()
                if node not in active_nodes:
			try:
                        	if manager.get_node_config(node).get("standby") == "True":
                                	return 5
                        	else:
                                	return 3
			except:
				return 3

                dc = manager.get_dc()
		if dc == None or dc == [] :
			return 1
                if node in dc:
                        if manager.get_node_config(node).get("standby") == "True":
                                return 4
                        return 0
                if manager.get_node_config(node).get("standby") == "True":
                        return 2

                return 1

	#neoshineha end ming.liu

	def select_view(self, type, name = None, status = None) :
		for child in self.mainview_sw.get_children() :
			self.mainview_sw.remove(child)

		(value, lower, upper, step_increment, page_increment, page_size) = (self.vadjr.value, self.vadjr.lower, self.vadjr.upper, self.vadjr.step_increment, self.vadjr.page_increment, self.vadjr.page_size)
		global selected_row_num

                tableview = TableView()
		self.mainview_sw.add_with_viewport(tableview.widget)
		if selected_row_num/9 > 0 :
			value = value + page_increment*selected_row_num/9
			self.vadjl.set_all(value, lower, upper, step_increment, page_increment, page_size)
		else :
			self.vadjl.set_all(value, lower, upper, step_increment, page_increment, page_size)
		#self.syncnodes(self.vadjl, None)
		self.syncrcs(self.vadjr, None)

		if self.view_status.get(type) != None :
			self.last_show_mode = self.view_status[type][0]
		else :
			self.last_show_mode = 0

		self.cur_type, self.cur_name, self.cur_status = type, name, status
		if self.cur_name == None:
			self.cur_name = ""

		if type == _("primitive"):
			type = "primitive"
		elif type == _("group"):
			type = "group"
		elif type == _("clone"):
			type = "clone"
		elif type == _("master"):
			type = "master"

		self.update_ui()
		if type == "configuration" :
			self.cur_view = ClusterView()
		elif type == "crm_config" and mode_level == 0 :
			self.cur_type = "crm_config_simple"
			self.cur_view = CRMConfigView()
			if not self.cur_view.update() :
				return
		elif type in ["primitive", "group", "clone", "master", "crm_config", "nodes", "resources", "constraints", "status", "rsc_defaults", "op_defaults", "acls", "fencing-topology"] \
				and manager.xml_nodes["cib"].getElementsByTagName(type) != [] :
			self.cur_view = ObjectView(manager.xml_nodes["cib"].getElementsByTagName(type)[0],
					is_topview = True, show_mode = self.last_show_mode)
		elif type in ["rsc_defaults", "op_defaults", "acls", "fencing-topology"] \
				and manager.xml_nodes["cib"].getElementsByTagName(type) == [] :
			self.cur_view = ObjectView(type, is_topview = True, missing_opt_obj_parent_type = "configuration",
					show_mode = self.last_show_mode)
		elif type == "management" :
			self.cur_view = ManageView()
		else :
			self.cur_view = None
			return

		#self.mainview_sw.add_with_viewport(widget)
		#self.cur_view.on_after_show()
		if self.view_status.get(self.cur_type) != None :
			self.cur_view.restore_status(self.view_status[self.cur_type])

	def do_cmd_with_pbar(self, cmd, title, msg, failed_msg, show_msgbox = True) :
		manager.async_do_cmd(cmd)
		pbar = ProgressPulse(title, msg, None, None,
				lambda : manager.async_ret_list.has_key(cmd))
		ret = pbar.run()
		if ret in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT] :
			return None

		manager.async_ret_lock.acquire()
		if manager.async_ret_list.has_key(cmd) :
			ret_list = manager.async_ret_list.pop(cmd)
		else :
			ret_list = None
		manager.async_ret_lock.release()

		if manager.failed_reason != "" :
			if show_msgbox :
				msgbox(top_window, manager.failed_reason)
			return None
                elif len(ret_list) < 1 :
                        if show_msgbox :
                                msgbox(top_window, failed_msg + _(": ") + _("Empty information returned"))
                        return None
                elif ret_list == None :
			if show_msgbox :
				msgbox(top_window, failed_msg + _(": ") + _("Nothing returned"))
			return None

		return ret_list
			
	# ui event handler	
	def on_quit(self, action) :
		if confirmbox(top_window, _("Do you want to quit ?")) == gtk.RESPONSE_YES :
			self.do_quit(action)

	def do_quit(self, action) :
		manager.save_profile()

		if manager.connected :
			self.confirm_record_pending()
		gtk.main_quit()
	
	def on_login(self, action) :
		dialog = gtk.Dialog(_("Login"),self.win_widget, gtk.DIALOG_MODAL,
			(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK))
		dialog.set_default_response(gtk.RESPONSE_OK)
		dialog.set_border_width(5)
		
		server = manager.profile["server"]
		user = manager.profile["user"]

		widgets = {}
		name_labels = []
		name_label_max_len = 0
		for key in ["server(:port)", "user_name", "password"] :
			hbox = gtk.HBox()
			name_label = gtk.Label(_(name_cap(key))+_(":"))
			name_label.set_alignment(0, 0.5)
			hbox.pack_start(name_label, False, padding=5)


			name_labels.append(name_label)
			name_label_len = name_label.size_request()[0]
			if name_label_len > name_label_max_len :
				name_label_max_len = name_label_len

			if key == "server(:port)" :
				widget = gtk.combo_box_entry_new_text()
				widget.append_text(server)
				widget.child.set_text(server)
				widget.child.set_activates_default(True)
			elif key == "user_name" :
				widget = gtk.combo_box_entry_new_text()
				widget.append_text(user)
				widget.child.set_text(user)
				widget.child.set_activates_default(True)
			if key == "password" :
				widget = gtk.Entry()
				widget.set_visibility(False)
				widget.set_activates_default(True)
				
			widgets[key] = widget
			hbox.pack_start(widget, True, padding=2)
			dialog.vbox.pack_start(hbox, False, padding=2)

		for name_label in name_labels :
			name_label.set_size_request(name_label_max_len, -1)

		dialog.set_focus(widgets["password"])		
		dialog.show_all()
		ret =  dialog.run()

		server = widgets["server(:port)"].child.get_text()
		user = widgets["user_name"].child.get_text()
		password = widgets["password"].get_text()

		dialog.destroy()

		if ret == gtk.RESPONSE_OK:
			if not manager.login(server, user, password):
				msgbox(top_window, manager.failed_reason)
				self.on_login("login")
				return
			else:
				manager.profile["server"] = server
				manager.profile["user"] = user
				manager.save_profile()
	
		self.update_ui()

	def on_logout(self, action) :
		if confirmbox(top_window, _("Do you want to logout ?")) == gtk.RESPONSE_YES :
			self.confirm_record_pending()
			manager.logout()
			self.update_ui()
			manager.record_pending_newly_enabled = False
			#neoshineha ming.liu add
	                for child in self.mainview_sw.get_children():
        	                self.mainview_sw.remove(child)
			for child in self.sub_vbox.get_children():
				self.sub_vbox.remove(child)
				self.sub_vbox.hide_all()
			#neoshineha ming.liu add end

	def confirm_record_pending(self) :
		if manager.xml_nodes.has_key("cib") and manager.find_attribute("op_defaults", "record-pending") == "true" \
                               and manager.record_pending_newly_enabled :
			retval = confirmbox(top_window, (_("\"Indicate pending operations\" has been activated.") + "\n"
					+ _("It could affect the performance.") + "\n"
					+ _("Turn it off ?")),
					default_response = gtk.RESPONSE_NO)
			if retval ==  gtk.RESPONSE_YES :
				manager.set_crm_attribute("op_defaults", "record-pending", "false")

	def on_shadow_action(self, action) :
		global top_window

		shadows = manager.do_cmd("get_shadows")
		if shadows == None or len(shadows) == 0 :
			msgbox(top_window, _("Cannot get any shadow CIB"))
			return

		shadow_list = [shadow[len("shadow."):] for shadow in shadows]
		shadow_list.sort()

		action_name = action.get_name()

		default_shadow = None
		if manager.active_cib != "" :
			#if action_name == "delete" :
			#	if manager.active_cib in shadow_list :
			#		shadow_list.remove(manager.active_cib)
			#		if len(shadow_list) == 0 :
			#			msgbox(top_window, _("The only one shadow CIB \"%s\" is currently active.")%manager.active_cib)
			#			return
			#else :
				default_shadow = manager.active_cib

		title_str = _(name_cap(action_name)) + " " + _("Shadow CIB")
		if action_name == "reset" :
			action_des = _(name_cap(action_name)) + " - " + _("Recreate the specified shadow CIB from the live CIB")
		elif action_name == "delete" :
			action_des = _("Delete the specified shadow CIB")
		elif action_name == "commit" :
			action_des = _(name_cap(action_name)) + " - " + _("Upload the specified shadow CIB to the cluster")

		shadow_action = kvbox(title_str, action_des,
				[Field("shadow_name", _("Shadow Name"), default_shadow, shadow_list, False, entry_editable = False)])

		if shadow_action == None :
			return

		shadow_name = shadow_action.get("shadow_name", "")

		if shadow_name == manager.active_cib and action_name == "delete" :
			reinit_name = ""
		else :
			reinit_name = manager.active_cib

		if shadow_name == manager.active_cib :
			manager.do_cmd("shutdown_cib")

		cmd_ret = manager.do_cmd("crm_shadow\n%s\n%s\ntrue" %(action_name, shadow_name))

		if cmd_ret == None :
			if manager.failed_reason.count("Please remember to unset the CIB_shadow variable") == 0 :
				if manager.failed_reason != "" :
					msgbox(top_window, manager.failed_reason)
		#else :
			elif action_name == "commit" and manager.active_cib != "" :
				retval = confirmbox(top_window, _("The shadow CIB \"%s\"has been successfully commited.")%shadow_name + "\n"
							+_("Switch to the live CIB?"),
						(gtk.STOCK_NO, gtk.RESPONSE_NO, gtk.STOCK_YES, gtk.RESPONSE_YES),
						_("Switch to the live CIB?"))
				if retval == gtk.RESPONSE_YES :
					reinit_name = ""

		if shadow_name == manager.active_cib :
			manager.do_cmd("init_cib\n%s"%(reinit_name))
			if manager.failed_reason != "" :
				msgbox(top_window, manager.failed_reason)
			else :
				manager.set_update()
		elif manager.active_cib != reinit_name :
			manager.do_cmd("switch_cib\n%s"%(reinit_name))
			if manager.failed_reason != "" :
				msgbox(top_window, manager.failed_reason)
			else :
				manager.set_update()

	def on_shadow_diff(self, action) :
		global top_window

		dialog = gtk.Dialog(_("Shadow CIB Diff"), top_window, gtk.DIALOG_MODAL,
				(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE, gtk.STOCK_SAVE, gtk.RESPONSE_APPLY))
		dialog.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_NORMAL)
		dialog.set_default_size(750, 550)
		dialog.set_default_response(gtk.RESPONSE_CLOSE)

		label = gtk.Label()
		label.set_markup('<b>' + _("Differences between the live CIB and the shadow CIB \"%s\"")%manager.active_cib + _(": ") + '</b>')
		label.set_alignment(0, 0)
		dialog.vbox.pack_start(label, False, padding = 5)

		sw = gtk.ScrolledWindow()
		sw.set_shadow_type(gtk.SHADOW_IN)
		sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		dialog.vbox.pack_start(sw, True)

		shadow_diff_text = gtk.TextView()
		shadow_diff_text.set_property("editable", False)
		shadow_diff_textbuffer = shadow_diff_text.get_buffer()
		sw.add(shadow_diff_text)

		reinit_name = manager.active_cib
		manager.do_cmd("shutdown_cib")

		cmd = "crm_shadow\ndiff\n\n"
		shadow_diff = window.do_cmd_with_pbar(cmd, _("Shadow CIB Diff"),
				_("Generating the shadow CIB differences may take a while..."),
				_("Failed to generate the shadow CIB differences"), False)

		if shadow_diff == None :
		#else :
			shadow_diff_textbuffer.set_text(manager.failed_reason)

		dialog.show_all()
		save_top_window = top_window
		top_window = dialog

		while True :
			ret = dialog.run()
			if ret == gtk.RESPONSE_APPLY :
				self.save_shadow_diff(shadow_diff_textbuffer)
			else :
				break

		dialog.destroy()
		top_window = save_top_window

		manager.do_cmd("init_cib\n%s"%(reinit_name))
		if manager.failed_reason != "" :
			msgbox(top_window, manager.failed_reason)
		else :
			manager.set_update()

	def save_shadow_diff(self, textbuffer) :
		default_name = manager.active_cib + ".diff"
		filter_list = ((_("Diff Files"), ("*.diff",)),
				(_("All Files"), ("*")))
		sfdlg = SelectFileDlg()
		(save_file, save_type) = sfdlg.select_file(default_name, filter_list)
		if save_file == None :
			return

		save_str = textbuffer.get_text(*textbuffer.get_bounds())

		if save_str == None :
			msgbox(top_window, _("Cannot save the shadow diff"))
			return

		try :
			fd = os.open(save_file, os.O_RDWR|os.O_CREAT|os.O_TRUNC, 0644)
		except OSError, msg :
			msgbox(top_window, _("System error") + _(": ") + str(msg))
			return

		try :
			 os.write(fd, save_str)
		except OSError, msg :
			msgbox(top_window, _("System error") + _(": ") + str(msg))
			os.close(fd)
			return
		os.close(fd)

	def on_create_cib(self, action) :
		global top_window

		shadows = manager.do_cmd("get_shadows")
		if shadows == None or len(shadows) == 0 :
			shadow_list = []
		else :
			shadow_list = [shadow[len("shadow."):] for shadow in shadows]
			shadow_list.sort()

		dialog = gtk.Dialog(_("Create Shadow CIB"), top_window, gtk.DIALOG_MODAL,
			(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK))
		dialog.set_default_response(gtk.RESPONSE_OK)
		dialog.set_border_width(5)

		combo_entries = {}
		checkbuttons = {}
		radiobuttons = {}

		for key in ["shadow_name", "live", "empty","force"] :
			hbox = gtk.HBox()
			if key in ["shadow_name"] :
				name_label = gtk.Label(_(name_cap(key))+_(":"))
				name_label.set_alignment(0, 0.5)
				hbox.pack_start(name_label, False, padding=2)

			if key == "shadow_name" :
				widget = gtk.combo_box_entry_new_text()
				for shadow in shadow_list :
					widget.append_text(shadow)
				widget.child.set_activates_default(True)
				combo_entries[key] = widget
			elif key == "live" :
				widget = gtk.RadioButton(None, _("A copy of the live CIB"))
				radiobuttons[key] = widget
				live_radio_btn = widget
			elif key == "empty" :
				widget = gtk.RadioButton(live_radio_btn, _("A new CIB with empty cluster configuration"))
				radiobuttons[key] = widget
			elif key == "force" :
				widget = gtk.CheckButton(_(name_cap(key)))
				checkbuttons[key] = widget

			hbox.pack_start(widget, True, padding=2)
			dialog.vbox.pack_start(hbox, False, padding=2)

		widgets = {}
		widgets["combo_entries"] = combo_entries
		widgets["checkbuttons"] = checkbuttons
		widgets["radiobuttons"] = radiobuttons

		widget_group = WidgetGroup(widgets)

		save_top_window = top_window
		top_window = dialog
		dialog.show_all()

		while True:
			ret = dialog.run()
			if ret in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT] :
				break

			create_shadow = widget_group.get_values()

			shadow_name = create_shadow.get("shadow_name", "")
			if shadow_name == "" :
				msgbox(top_window, _("Please specify a name for the shadow CIB."))
				continue
			if shadow_name == "Live" or shadow_name == "live" :
				msgbox(top_window, _("Please specify another name for avoiding confusion."))
				continue
			elif shadow_name == manager.active_cib :
				msgbox(top_window, _("A shadow CIB \"%s\" already exists and it's currently active.")%(shadow_name))
				continue
			elif shadow_name in shadow_list and create_shadow.get("force", "") != "true" :
				msgbox(top_window, _("A shadow CIB \"%s\" already exists.")%(shadow_name) + "\n" + 
						_("Specify another name, or select \"Force\" if you want to override it."))
				continue

			if create_shadow.get("live") == "true" :
				create_cmd = "create"
			else :
				create_cmd = "create-empty"

			cmd_ret = manager.do_cmd("crm_shadow\n%s\n%s\n%s"
					%(create_cmd, shadow_name, create_shadow.get("force", "")))
			if cmd_ret == None :
				if manager.failed_reason == "" :
					#msgbox(top_window, _("Failed creating shadow CIB"))
					break

				if manager.failed_reason.count("A new shadow instance was created") == 0 :
					msgbox(top_window, manager.failed_reason)
					continue
			#else :
				retval = confirmbox(top_window, _("A new shadow CIB \"%s\" has been successfully created.")%shadow_name + "\n"
							+_("Switch to it now?"),
						(gtk.STOCK_NO, gtk.RESPONSE_NO, gtk.STOCK_YES, gtk.RESPONSE_YES),
						_("Switch to the new created shadow CIB \"%s\"?")%shadow_name)
				if retval == gtk.RESPONSE_YES :
					manager.do_cmd("switch_cib\n%s"%(create_shadow.get("shadow_name", "")))
					manager.set_update()
				break

		top_window = save_top_window
		dialog.destroy()


	def on_switch_cib(self, action, current, switch_list) :
		switch_name = switch_list[action.get_current_value()]
		if switch_name == "live" :
			manager.do_cmd("switch_cib\n")
		else :
			manager.do_cmd("switch_cib\n%s"%(switch_name[len("shadow."):]))
		if manager.failed_reason != "" :
                        msgbox(top_window, manager.failed_reason + "\n"+ _("Or you don't have the permission."))

		manager.set_update()

	def render_switch_submenu(self, action) :
		for menuitem in self.switch_submenu.get_children() :
			self.switch_submenu.remove(menuitem)

		shadows = manager.do_cmd("get_shadows")
		if manager.failed_reason != "" :
			msgbox(top_window, manager.failed_reason)
			return
		if shadows == None or len(shadows) == 0 :
			return

		#shadow_list = [shadow[len("shadow."):] for shadow in shadows]
		shadow_list = shadows[:]
		shadow_list.sort()

		switch_list = shadow_list[:]
		switch_list.insert(0, "live")

		switch_radio_actions = [('live', None, _('Live'), None, None, 0)]
		for i in range(len(shadow_list)) :
			shadow = shadow_list[i]
			switch_radio_actions.append((shadow, None, shadow[len("shadow."):], None, None, i+1))

		default_active = 0
		if manager.active_cib != "" :
			active_shadow = "shadow." + manager.active_cib
			if active_shadow in switch_list :
				default_active = switch_list.index(active_shadow)

		switch_radio_actiongroup = gtk.ActionGroup("switch")
		switch_radio_actiongroup.add_radio_actions(switch_radio_actions, default_active, self.on_switch_cib, switch_list)

		for switch_name in switch_list :
			action = switch_radio_actiongroup.get_action(switch_name)
			action.set_accel_group(self.accelgroup)
			switch_menuitem = action.create_menu_item()
			self.switch_submenu.append(switch_menuitem)
			if switch_name == "live" :
				separator = gtk.SeparatorMenuItem()
				self.switch_submenu.append(separator)

		self.switch_submenu.show_all()

	def on_transition_info(self, action) :
		tidlg = TransitionInfoDlg()

	def on_cluster_report(self, action) :
		rpdlg = TimeFrameDlg()
		report_params = rpdlg.set_params(_("Cluster Report"), (False, True, True, False))
		if report_params == None :
			return

		report_params["ftime"] = time.strftime("%F %T", report_params["ftime"])
		if report_params.get("ttime") != None :
			report_params["ttime"] = time.strftime("%F %T", report_params["ttime"])

		report_cmd = "gen_cluster_report\n%s\n%s"%(report_params["ftime"], report_params.get("ttime", ""))

		str_list = window.do_cmd_with_pbar(report_cmd, _("Cluster Report"), 
					_("Generating the cluster report may take a while,")+"\n"
					+_("depending on the size of logs..."),
					_("Failed to generate the cluster report"))
		if str_list != None :
			self.save_cluster_report(str_list)

	def save_cluster_report(self, str_list) :
		if str_list == None or len(str_list) < 2 :
			msgbox(top_window, _("Failed to generate the cluster report"))
			return

		default_filename = os.path.basename(str_list[0])
		default_filetype = default_filename.split(".")[-1]

		base64_str = "\n".join(str_list[1:])
		try :
			bin_str = binascii.a2b_base64(base64_str)
		except binascii.Incomplete, msg :
			msgbox(top_window, _("Incomplete data") + (": ") + str(msg))
			return

		try :
			(fd, tmp_file) = tempfile.mkstemp(suffix = ".tar." + default_filetype, prefix = "cluster-report-")
		except IOError, msg :
			msgbox(top_window, _("I/O error") + _(": ") + str(msg))
			return

		#try :
		#	fd = os.open(save_file, os.O_RDWR|os.O_CREAT|os.O_TRUNC, 0644)
		#except OSError, msg :
		#	msgbox(top_window, _("System error") + _(": ") + str(msg))
		#	return

		try :
			os.write(fd, bin_str)
		except OSError, msg :
			msgbox(top_window, _("System error") + _(": ") + str(msg))
			os.close(fd)
			return
		os.close(fd)

		self.des_cluster_report(tmp_file)

	def des_cluster_report(self, tmp_file) :
		tmp_dir = os.path.dirname(tmp_file)

		default_filename = os.path.basename(tmp_file)
		default_filetype = default_filename.split(".")[-1]

		try :
			tmp_tarfile = tarfile.open(tmp_file, "r:"+default_filetype)
		except IOError, msg :
			msgbox(top_window, _("I/O error") + _(": ") + str(msg))
			return
		except tarfile.TarError, msg :
			msgbox(top_window, _("Tar error") + _(": ") + "%s: '%s'"%(str(msg), tmp_file))
			return
			
		try :
			file_list = tmp_tarfile.getnames()
			for filename in file_list :
				tmp_tarfile.extract(filename, tmp_dir)
		except tarfile.TarError, msg :
			msgbox(top_window, _("Tar error") + _(": ") + "%s: '%s'"%(str(msg), tmp_file))
			tmp_tarfile.close()
			return

		tmp_tarfile.close()
		os.unlink(tmp_file)	

		des_filename = None
		for filename in file_list :
			if filename.endswith("description.txt") :
				des_filename = filename
				break

		if des_filename != None :
			des_filepath = os.path.join(tmp_dir, des_filename)

			try :
				des_f = open(des_filepath, "r+")
			except IOError, msg :
				msgbox(top_window, _("I/O error") + _(": ") + str(msg))
				self.delete_files(tmp_dir, file_list)
				return

			try :
				file_lines = des_f.readlines()
			except IOError, msg :
				msgbox(top_window, _("I/O error") + _(": ") + str(msg))
				des_f.close()
				self.delete_files(tmp_dir, file_list)
				return

			des_report = DesReportDlg(file_lines)
			new_file_lines = des_report.run()

			if new_file_lines == None :
				new_file_lines = file_lines

			try :
				des_f.seek(0)
				des_f.truncate()
				des_f.writelines(new_file_lines)
			except IOError, msg :
				msgbox(top_window, _("I/O error") + _(": ") + str(msg))
				des_f.close()
				self.delete_files(tmp_dir, file_list)
				return

			des_f.close()

		sfdlg = SelectFileDlg()
		(save_file, save_type) = sfdlg.select_file(default_filename)
		if save_file == None :
			self.delete_files(tmp_dir, file_list)
			return

		try :
			new_tarfile = tarfile.open(save_file, "w:"+default_filetype)
		except IOError, msg :
			msgbox(top_window, _("I/O error") + _(": ") + str(msg))
			self.delete_files(tmp_dir, file_list)
			return
		except tarfile.TarError, msg :
			msgbox(top_window, _("Tar error") + _(": ") + "%s: '%s'"%(str(msg), save_file))
			self.delete_files(tmp_dir, file_list)
			return

		current_arcname = os.path.commonprefix(file_list).split(os.sep)[0]
		if current_arcname != '' :
			file_basename = os.path.basename(save_file)

			new_arcname = None
			for suffix in [".tar.gz", ".tgz", ".gz", ".tar.bz2", ".tbz", ".bz2"] :
				if save_file.endswith(suffix) :
					new_arcname = file_basename[:file_basename.rfind(suffix)]
					break
			if new_arcname == None :
				new_arcname = file_basename

			folder = os.path.join(tmp_dir, current_arcname)
			try :
				new_tarfile.add(folder, new_arcname)
			except IOError, msg :
				msgbox(top_window, _("I/O error") + _(": ") + str(msg))
				self.delete_files(tmp_dir, file_list)
				return
			except tarfile.TarError, msg :
				msgbox(top_window, _("Tar error") + _(": ") + "%s: '%s'"%(str(msg), save_file))
				new_tarfile.close()
				self.delete_files(tmp_dir, file_list)
				return
			new_tarfile.close()
			self.delete_files(tmp_dir, file_list)

		else :
			for filename in file_list :
				file_path = os.path.join(tmp_dir, filename)
				try :
					new_tarfile.add(file_path, recursive=False)
				except IOError, msg :
					msgbox(top_window, _("I/O error") + _(": ") + str(msg))
					new_tarfile.close()
					self.delete_files(tmp_dir, file_list)
					return
				except tarfile.TarError, msg :
					msgbox(top_window, _("Tar error") + _(": ") + "%s: '%s'"%(str(msg), save_file))
					new_tarfile.close()
					self.delete_files(tmp_dir, file_list)
					return
			new_tarfile.close()
			self.delete_files(tmp_dir, file_list)

	def delete_files(self, save_dir, file_list) :
		dir_list = []
		for filename in file_list :
			file_path = os.path.join(save_dir, filename)
			try :
				mode = os.lstat(file_path)[ST_MODE]
			except OSError, msg :
				msgbox(top_window, _("System error") + _(": ") + str(msg))
				continue

			if S_ISDIR(mode) :
				dir_list.append(file_path)
			else :
				try :
					os.unlink(file_path)
				except OSError, msg :
					msgbox(top_window, _("System error") + _(": ") + str(msg))
					continue

		for dir_path in dir_list :
			if os.access(dir_path, os.F_OK) :
				delete_dir(dir_path)

	def on_about(self, action) :
		global top_window
		name = _("NeoKylin HA Cluster Software (NKHA) V7.0")
		version = ""
		comments = _("NeoKylin HA Management Client")
		copyright = _("\nCopyright CS2C\n")

		if not pygtk_newer(2, 6) :
			dialog = gtk.Dialog(_("About") + " " + name, top_window, gtk.DIALOG_MODAL)
			dialog.set_has_separator(False)
			dialog.set_border_width(5)
			dialog.set_resizable(False)
			dialog.vbox.set_spacing(5)
			im = gtk.Image()
			im.set_from_stock("ha", gtk.ICON_SIZE_DIALOG)
			dialog.vbox.pack_start(im, False)
			markup_text_list = ['<span size="large"><b>' + name + ' ' + version  + '</b></span>',
						comments,
						'<span size="small">' + copyright + '</span>']
			for markup_text in markup_text_list :
				markup_label = gtk.Label()
				markup_label.set_justify(gtk.JUSTIFY_CENTER)
				markup_label.set_selectable(True)
				widget = markup_label
					
				markup_label.set_markup(markup_text)
				dialog.vbox.pack_start(widget, False)

			close_btn = dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CANCEL)
			close_btn.grab_default()
			close_btn.grab_focus()

			dialog.show_all()
		else :
			dialog = gtk.AboutDialog()
			dialog.set_transient_for(top_window)

			dialog.set_name(name)
			dialog.set_version(version)
			dialog.set_copyright(copyright)
			dialog.set_comments(comments)
			dialog.set_logo(gtk.gdk.pixbuf_new_from_file_at_size('@HA_DATADIR@/heartbeat-gui/ha.png', 200, 200))

		save_top_window = top_window
             	top_window = dialog
		dialog.run()
		
		top_window = save_top_window
		dialog.destroy()

	def open_url(self, widget, link) :
		webbrowser.open(link)

	def change_mode_level(self, action, current) :
		global mode_level
		last_mode_level = mode_level
		mode_level = action.get_current_value()
		if mode_level and last_mode_level == 0:
			self.merge_id = self.uimanager.add_ui_from_string(self.ui_xml1)
		elif last_mode_level and mode_level == 0:
			self.uimanager.remove_ui(self.merge_id)
			self.merge_id = 0

		self.update()

	def load_icon(self, name, file) :
		icons = gtk.IconFactory()
		icons.add(name,gtk.IconSet(gtk.gdk.pixbuf_new_from_file(file)))
		icons.add_default()

	# constructor	
	def __init__(self) :
		# create window
		win_widget = gtk.Window()
		win_widget.connect("delete_event", self.on_delete_event)
		win_widget.set_title(_("NeoKylin HA Management Client"))
		win_widget.set_default_size(manager.profile["width"], manager.profile["height"])
		win_widget.set_icon_from_file("@HA_DATADIR@/heartbeat-gui/ha.png")

		# add the icons to gtk stock
		self.load_icon("ha", "@HA_DATADIR@/heartbeat-gui/ha.png")
		if True: #not pygtk_newer(2, 6) :
			self.load_icon("ha-login","@HA_DATADIR@/heartbeat-gui/login.png")
			self.load_icon("ha-logout","@HA_DATADIR@/heartbeat-gui/logout.png")
		self.load_icon("ha-standby-node","@HA_DATADIR@/heartbeat-gui/standby-node.png")
		self.load_icon("ha-active-node","@HA_DATADIR@/heartbeat-gui/active-node.png")
		self.load_icon("ha-del-node","@HA_DATADIR@/heartbeat-gui/delete-node.png")
		self.load_icon("ha-start-resource","@HA_DATADIR@/heartbeat-gui/start-resource.png")
		self.load_icon("ha-stop-resource","@HA_DATADIR@/heartbeat-gui/stop-resource.png")
		self.load_icon("ha-master-resource","@HA_DATADIR@/heartbeat-gui/master-resource.png")
		self.load_icon("ha-slave-resource","@HA_DATADIR@/heartbeat-gui/slave-resource.png")
		self.load_icon("ha-manage-resource","@HA_DATADIR@/heartbeat-gui/manage-resource.png")
		self.load_icon("ha-unmanage-resource","@HA_DATADIR@/heartbeat-gui/unmanage-resource.png")

		self.load_icon("administration","@HA_DATADIR@/heartbeat-gui/administration.png")
		self.load_icon("record-pending","@HA_DATADIR@/heartbeat-gui/record-pending.png")

		#self.load_icon("nodes","@HA_DATADIR@/heartbeat-gui/nodes.png")
		#self.load_icon("node","@HA_DATADIR@/heartbeat-gui/node.png")

		self.load_icon("failed","@HA_DATADIR@/heartbeat-gui/failed.png")
		self.load_icon("running","@HA_DATADIR@/heartbeat-gui/running.png")
		self.load_icon("stopped","@HA_DATADIR@/heartbeat-gui/stopped.png")
		self.load_icon("dirty-stopped","@HA_DATADIR@/heartbeat-gui/dirty-stopped.png")
		self.load_icon("starting","@HA_DATADIR@/heartbeat-gui/starting.png")
		self.load_icon("stopping","@HA_DATADIR@/heartbeat-gui/stopping.png")

		#self.load_icon("expert-mode","@HA_DATADIR@/heartbeat-gui/expert-mode.png")

		#neoshineha ming.liu
		self.load_icon("quit-icon","@HA_DATADIR@/heartbeat-gui/exit.png")
                self.load_icon("ha-cleanup-resource","@HA_DATADIR@/heartbeat-gui/cleanup-resource.png")
                #self.load_icon("ha-default-resource","@HA_DATADIR@/heartbeat-gui/default-resource.png")
		#self.load_icon("ha-drbd","@HA_DATADIR@/heartbeat-gui/drbd_logo.png")
		self.load_icon("gfs-icon","@HA_DATADIR@/heartbeat-gui/drbd_logo.png")
		self.load_icon("mirror-icon","@HA_DATADIR@/heartbeat-gui/drbd_logo.png")
                self.load_icon("alarm-icon","@HA_DATADIR@/heartbeat-gui/alert.png")
                self.load_icon("sfex-icon", "@HA_DATADIR@/heartbeat-gui/sfex.png")
                self.load_icon("addnodeviewer-icon","@HA_DATADIR@/heartbeat-gui/addnode.png")
                self.load_icon("mainnodeviewer-icon","@HA_DATADIR@/heartbeat-gui/mainnode.png")
                self.load_icon("addhbviewer-icon","@HA_DATADIR@/heartbeat-gui/addhb.png")
                #self.load_icon("rscattrs-icon","@HA_DATADIR@/heartbeat-gui/addhb.png")
                self.load_icon("rscattr-icon","@HA_DATADIR@/heartbeat-gui/rscattr-icon.png")
                #self.load_icon("rscparam-icon","@HA_DATADIR@/heartbeat-gui/addhb.png")
                #self.load_icon("rscop-icon","@HA_DATADIR@/heartbeat-gui/addhb.png")
                #self.load_icon("groupattrs-icon","@HA_DATADIR@/heartbeat-gui/addhb.png")
                #self.load_icon("groupattr-icon","@HA_DATADIR@/heartbeat-gui/rscattr-icon.png")
                #self.load_icon("grouparam-icon","@HA_DATADIR@/heartbeat-gui/addhb.png")
                self.load_icon("rename-icon","@HA_DATADIR@/heartbeat-gui/rename.png")
                self.load_icon("move-icon","@HA_DATADIR@/heartbeat-gui/move.png")
                self.load_icon("ha-migrate-resource","@HA_DATADIR@/heartbeat-gui/migrate.png")
                self.load_icon("ha-unmigrate-resource","@HA_DATADIR@/heartbeat-gui/unmigrate.png")
                self.load_icon("constraint-icon","@HA_DATADIR@/heartbeat-gui/constraint.png")
		self.load_icon("ha-add-resource","@HA_DATADIR@/heartbeat-gui/add-resource.png")
                self.load_icon("ha-remove-resource","@HA_DATADIR@/heartbeat-gui/remove-resource.png")
		self.load_icon("ha-up-resource","@HA_DATADIR@/heartbeat-gui/up-resource.png")
                self.load_icon("ha-down-resource","@HA_DATADIR@/heartbeat-gui/down-resource.png")
		#self.load_icon("addnode-icon","@HA_DATADIR@/heartbeat-gui/down-resource.png")
		self.load_icon("diskhb-icon","@HA_DATADIR@/heartbeat-gui/diskhb.png")
		self.load_icon("manual-icon","@HA_DATADIR@/heartbeat-gui/stock_info_24.png")
                self.load_icon("about-icon","@HA_DATADIR@/heartbeat-gui/stock_about_24.png")
                self.load_icon("register-icon","@HA_DATADIR@/heartbeat-gui/stock_key_24.png")
		self.load_icon("deploy-icon","@HA_DATADIR@/heartbeat-gui/import.png")
		self.load_icon("script-icon","@HA_DATADIR@/heartbeat-gui/script.png")
		self.load_icon("globalparam-icon","@HA_DATADIR@/heartbeat-gui/globalparam.png")
		self.load_icon("upgrade-icon","@HA_DATADIR@/heartbeat-gui/update.png")
		self.load_icon("transition-icon","@HA_DATADIR@/heartbeat-gui/transition.png")
		self.load_icon("report-icon","@HA_DATADIR@/heartbeat-gui/report.png")
		self.load_icon("switch-icon","@HA_DATADIR@/heartbeat-gui/switch.png")
		#neoshineha end ming.liu

		# create ui-manager
		ui_xml = '''
		<ui>
			<menubar name="menubar">
				<menu action="connection">
					<menuitem action="login"/>
					<menuitem action="logout"/>
					<separator/>
					<menuitem action="quit"/>
				</menu>
				<menu action="view">
                                        <menuitem action="simple-mode"/>
                                        <menuitem action="expert-mode"/>
                                        <menuitem action="hack-mode"/>
                                </menu>
				<menu action="resources">
					<menuitem action="addrsc"/>
					<menuitem action="delrsc"/>
					<menuitem action="startrsc"/>
	                                <menuitem action="stoprsc"/>
                	                <menuitem action="cleanuprsc"/>
					<menuitem action="renamersc"/>
                                        <separator/>
        	                        <menuitem action="uprsc"/>
                	                <menuitem action="downrsc"/>
                        	        <menuitem action="movetogroup"/>
                                	<menuitem action="mainnode"/>
					<separator/>
                                        <menuitem action="migratersc"/>
                                        <menuitem action="unmigratersc"/>
	                                <separator/>
					<menuitem action="reprobe"/>
					<menuitem action="maintenance-mode"/>
        	                        <menuitem action="rscattributes"/>
                                </menu>
				<menu action="configuration">
                                        <menuitem action="alarm"/>
					<menuitem action="nethb"/>
                                        <menuitem action="gfs"/>
                                        <separator/>
                                        <menuitem action="standby"/>
                                        <menuitem action="active"/>
                                        <menuitem action="delnode"/>
                                        <separator/>
					<menuitem action="globalparameter"/>
                                </menu>
				<menu action="tools">
					<menuitem action="transition-info"/>
                                        <menuitem action="report"/>
					<separator/>
					<menuitem action="rapid-deploy"/>
				</menu>
				<menu action="help">
					<menuitem action="about"/>
					<menuitem action="manual"/>
					<menuitem action="upgrade"/>
                                        <menuitem action="register"/>
				</menu>
			</menubar>
			<popup name="connection_popup">
				<menuitem action="login"/>
				<menuitem action="logout"/>
				<menuitem action="quit"/>
			</popup>
			<popup action="node_popup">
				<menuitem action="standby"/>
                                <menuitem action="active"/>
                                <menuitem action="delnode"/>
                        </popup>
			<popup name="resource_popup">
                                <menuitem action="addrsc"/>
                                <menuitem action="delrsc"/>
				<menuitem action="startrsc"/>
                                <menuitem action="stoprsc"/>
                                <menuitem action="cleanuprsc"/>
				<menuitem action="renamersc"/>
                                <separator/>
				<menuitem action="uprsc"/>
                                <menuitem action="downrsc"/>
                                <menuitem action="movetogroup"/>
                                <menuitem action="mainnode"/>
                                <separator/>
                                <menuitem action="migratersc"/>
                                <menuitem action="unmigratersc"/>
				<separator/>
                                <menuitem action="reprobe"/>
                                <menuitem action="maintenance-mode"/>
                                <menuitem action="rscattributes"/>
                        </popup>
			<popup name="global_popup">
				<menuitem action="addrsc"/>
                                <menuitem action="globalparameter"/>
                        </popup>
			<popup name="group_popup">
				<menuitem action="addrsc"/>
                                <menuitem action="delrsc"/>
                                <menuitem action="startrsc"/>
                                <menuitem action="stoprsc"/>
                                <menuitem action="cleanuprsc"/>
                                <menuitem action="renamersc"/>
                                <separator/>
                                <menuitem action="uprsc"/>
                                <menuitem action="downrsc"/>
                                <menuitem action="mainnode"/>
                                <separator/>
                                <menuitem action="migratersc"/>
                                <menuitem action="unmigratersc"/>
                                <separator/>
                                <menuitem action="reprobe"/>
                                <menuitem action="maintenance-mode"/>
                                <menuitem action="rscattributes"/>
                        </popup>
			<popup action="tools_popup">
                                <menuitem action="transition-info"/>
                                <menuitem action="report"/>
                                <separator/>
                                <menuitem action="simple-mode"/>
                                <menuitem action="expert-mode"/>
                                <menuitem action="hack-mode"/>
                        </popup>
			<toolbar name="toolbar">
				<toolitem action="login"/>
				<toolitem action="logout"/>
				<separator/>
				<toolitem action="addrsc"/>
                                <toolitem action="delrsc"/>
				<toolitem action="movetogroup"/>
                                <separator/>
				<toolitem action="startrsc"/>
                                <toolitem action="stoprsc"/>
                                <toolitem action="cleanuprsc"/>
                                <separator/>
                                <toolitem action="uprsc"/>
                                <toolitem action="downrsc"/>
                                <toolitem action="mainnode"/>
                                <separator/>
                                <toolitem action="migratersc"/>
                                <toolitem action="unmigratersc"/>
                                <separator/>
                                <toolitem action="standby"/>
                                <toolitem action="active"/>
                                <toolitem action="delnode"/>

			</toolbar>
		</ui>'''

		self.ui_xml1 = '''
		<ui>
			<menubar name="menubar">
				<menu action="configuration">
					<menuitem action="constraint"/>
                                </menu>
				<menu action="tools">
					<menuitem action="script-generator"/>
				</menu>
			</menubar>
                        <popup name="global_popup">
                                <menuitem action="constraint"/>
                        </popup>
		</ui>'''

		self.merge_id = 0

		uimanager = gtk.UIManager()

		self.accelgroup = uimanager.get_accel_group()
		win_widget.add_accel_group(self.accelgroup)

		actiongroup = gtk.ActionGroup('haclient')

		if False: #pygtk_newer(2, 6) :
			login_icon = gtk.STOCK_CONNECT
			logout_icon = gtk.STOCK_DISCONNECT
		else :
			login_icon = "ha-login"
			logout_icon = "ha-logout"

		#neoshineha ming.liu
                if False: #pygtk_newer(2, 6) :
                        startrsc_icon = gtk.STOCK_MEDIA_PLAY
                        stoprsc_icon = gtk.STOCK_MEDIA_STOP
                else :
                        startrsc_icon = "ha-start-resource"
                        stoprsc_icon = "ha-stop-resource"
		#neoshineha end ming.liu

		actiongroup.add_actions([
			('connection', None, _('_Connection')),
			('login', login_icon, _('Log_in'), None, _('login to cluster'), self.on_login),
			('logout', logout_icon, _('Log_out'), None, _('logout from cluster'), self.on_logout),
			('quit', "quit-icon", _('_Quit'), None,_('Quit the Program'), self.on_quit),
			('view', None, _('_View')),
			('shadow', None, _('_Shadow')),
			('new', gtk.STOCK_NEW, _('_New'), None,_('Create a new shadow CIB'), self.on_create_cib),
			('diff', gtk.STOCK_COPY, _('Di_ff'), None, _('Differences between the live CIB and the shadow CIB'), self.on_shadow_diff),
			('reset', None, _('_Reset'), None, _('Recreate a shadow CIB from the live CIB'), self.on_shadow_action),
			('delete', gtk.STOCK_DELETE, _('_Delete'), None, _('Delete a shadow CIB'), self.on_shadow_action),
			('commit', gtk.STOCK_SAVE, _('_Commit'), None, _('Upload a shadow CIB to the cluster'), self.on_shadow_action),
			('switch', None, _('_Switch'), None, _('Switch working CIB'), self.render_switch_submenu),
			('tools', None, _('_Tools')),
			('transition-info', "transition-icon", _('_Transition Information'), None,
				_('Show Transition Information'), self.on_transition_info),
			('report', "report-icon", _('Cluster Re_port'), None, _('generate a cluster report'), self.on_cluster_report),
			('help', None, _('_Help')),
			('about', "about-icon", _('_About'), None, _('About'), self.on_about),
			#neoshineha ming.liu
			('configuration', None, _('Con_figuration')),
			('resources', None, _('_Resource')),
			('addrsc', "ha-add-resource", _('_Add Resource'), None,_('Add Resource'), self.on_add_rsc),
                        ('delrsc', "ha-remove-resource", _('_Delete Resource'), None,_('Delete Resource'), self.on_del_item),
			('uprsc', "ha-up-resource", _('Move _Up Resource'), None,_('Move Up Resource'), self.on_item_move),
                        ('downrsc', "ha-down-resource", _('Move Do_wn Resource'), None,_('Move Down Resource'),
                                 self.on_item_move),
			('diskhb', "diskhb-icon", _('_Disk Heartbeat Configuration'), None, _('Disk Heartbeat Configuration'), self.on_add_diskhb),
			('gfs', "gfs-icon", _('_GFS Configuration'), None,_('GFS Configuration'), self.on_gfs),
                        ('alarm', "alarm-icon", _("Ala_rm Configuration"), None, _('Alarm Configuration'), self.on_item_alarm),
                        ('movetogroup', "move-icon", _('Move To _Group'), None, _('Move To Group'), self.on_move_to_group),
                        ('addnode', "addnodeviewer-icon",  _('Adding and Removing Cluster _Nodes'), None, _('Adding and Removing Cluster Nodes'),
                                self.on_add_item),
                        ('mainnode', "mainnodeviewer-icon",  _('Resource _Location'), None, _('Resource Location'),
                                self.on_main_node),
			('globalparameter', "globalparam-icon",  _('_Preferences'), None, _('Preferences'),
                                self.on_add_item),
			('addhb', "addhbviewer-icon", _('_Heartbeats Configuration'), None, _('Heartbeats Configuration'), None),
                        ('nethb', "nethbviewer-icon", _('Networ_kheartbeats Configuration'), None, _('Network Heartbeats Configuration'),
                                self.on_add_nethb),
                        ('rscattributes', "rscattr-icon",  _('Resource Attri_butes'), None, _('Resource Attributes'),
                                self.on_rsc_attr),
                        ('renamersc', "rename-icon",  _('Re_name Resource'), None, _('Rename Resource'),
                                self.on_rename),
                        ('constraint', "constraint-icon", _('_Constraints'), None, _('Constraints'), self.on_add_item),

                        ('startrsc', startrsc_icon, _('Sta_rt'), None,_('Start resource'), self.on_rsc_action),
                        ('stoprsc', stoprsc_icon, _('St_op'), None,_('Stop resource'), self.on_rsc_action),
                        ('cleanuprsc', "ha-cleanup-resource", _('_Cleanup Resource'), None,_('Cleanup resource'), self.on_rsc_cleanup),
                        ('migratersc', "ha-migrate-resource", _('Migra_te Resource'), None, _('Migrate a resource to specified node'),
                                self.on_migrate_rsc),
                        ('unmigratersc', "ha-unmigrate-resource", _('Cl_ear Migrate Constraints'),
                                None, _('Clear constraints created by migrate'),
                                self.on_unmigrate_rsc),
                        ('unmanagersc', "ha-unmanage-resource", _('_Unmanage Resource'), None, _('Put a resource into unmanaged mode'),
                                self.on_manage_rsc),
                        ('managersc', "ha-manage-resource", _('_Manage Resource'), None, _('Put a resource into managed mode'),
                                self.on_manage_rsc),
                        ('refresh', gtk.STOCK_REFRESH, _('Re_fresh Resources'), None, _('Refresh CIB from the LRM status'),
                                self.on_crm_rsc_cmd),
                        ('reprobe', gtk.STOCK_REFRESH, _('Re_probe Resources'), None, _('Reprobe for resources started outside of the CRM'),
                                self.on_crm_rsc_cmd),
                        ('standby', "ha-standby-node", _('_Standby'), None,_('Make the node standby'), self.on_standby),
                        ('active', "ha-active-node", _('_Active'), None,_('Make the node active'), self.on_active),
                        ('delnode', "ha-del-node", _('Node D_elete'), None,_('Delete the node'), self.on_del_node),
			('manual', 'manual-icon', _('_Manual'), None, None, self.on_manual),
                        ('register', 'register-icon', _('_Register'), None, None, self.on_register),
			('rapid-deploy', 'deploy-icon', _('_Rapid Deployment Import'), None, None, self.on_rapid_deploy),
			('script-generator', 'script-icon', _('_Script Generator'), None, None, self.on_script_generator),
			('upgrade', "upgrade-icon", _('_Upgrade'), None,
                                _('Upgrade'), self.on_upgrade_src)
			])
		toggle_tool_actions = [
			#('group-by-node', gtk.STOCK_SORT_DESCENDING, _('_Group By Node'), None, _('Group resources by node'), self.change_group_mode),
                        ('maintenance-mode', "administration", _('_Maintenance Mode'), None,
                                _('Switch to maintenance mode'), self.change_maintenance_mode),
                        ('record-pending', "record-pending", _('_Indicate Pending Operations'), None,
                                _('Indicate pending(starting/stopping) operations'), self.change_record_pending),
			#neoshineha end ming.liu
			]

		uimanager.insert_action_group(actiongroup, 0)

		#neoshineha ming.liu
		self.toggle_tool_action_group = gtk.ActionGroup("toggle_tools")
                self.toggle_tool_action_group.add_toggle_actions(toggle_tool_actions)

                uimanager.insert_action_group(self.toggle_tool_action_group, 1)
		#neoshineha end ming.liu

		radio_tool_actions = [
			('simple-mode', None, _('_Simple Mode'), None, _('Switch to simple mode'), 0),
			('expert-mode', None, _('_Expert Mode'), None, _('Switch to expert mode'), 1),
			('hack-mode', None, _('_Hack Mode'), None, _('Switch to hack mode'), 2),
			]

		self.radio_tool_action_group = gtk.ActionGroup("radio_mode_level")
		self.radio_tool_action_group.add_radio_actions(radio_tool_actions, 0, self.change_mode_level)
		uimanager.insert_action_group(self.radio_tool_action_group, 1)

		uimanager.add_ui_from_string(ui_xml)

		# put componets to window
		vbox = gtk.VBox()
		win_widget.add(vbox)

		menubar = uimanager.get_widget('/menubar')
		vbox.pack_start(menubar, False)


		toolbar = uimanager.get_widget('/toolbar')
		toolbar.set_style(gtk.TOOLBAR_ICONS)
		toolbar.set_orientation(gtk.ORIENTATION_HORIZONTAL)
		toolbar.get_settings().set_property("gtk-toolbar-icon-size", gtk.ICON_SIZE_DND)
		toolbar.set_property("height-request", 64)
		toolbar.modify_bg(gtk.STATE_NORMAL, toolbar.get_colormap().alloc_color("#cccccc"))
		vbox.pack_start(toolbar, False)

		vpaned1 = gtk.VPaned()
		vbox.pack_start(vpaned1)

		hpaned = gtk.HPaned()
		#vbox.pack_start(hpaned)

		#maintree = MainTree("cib")
		maintree_sw = gtk.ScrolledWindow()
		maintree_sw.set_shadow_type(gtk.SHADOW_IN)

		maintree_sw.set_policy(gtk.POLICY_ALWAYS, gtk.POLICY_ALWAYS)

		self.maintree = MainTree()
		maintree_sw.add(self.maintree.widget)

		self.manage_tree = self.maintree
		#self.manage_tree = ManageTree()
                #top_vbox.pack_start(self.manage_tree.widget)
                self.maintree.tree.connect("cursor-changed", self.on_after_show)
                #self.maintree.tree.connect("event-after", self.on_right_click)

		#maintree_sw.add(maintree)

		#maintree_frame = gtk.Frame()
		#maintree_frame.add(maintree_sw)
		hpaned.add1(maintree_sw)

		mainview_sw = gtk.ScrolledWindow()
		mainview_sw.set_shadow_type(gtk.SHADOW_IN)
		mainview_sw.set_policy(gtk.POLICY_ALWAYS, gtk.POLICY_ALWAYS)

                vpaned = gtk.VPaned()
                vpaned.add1(mainview_sw)
		mainview_sw.set_property("height-request", 300)

		#mainview_frame = gtk.Frame()
		#mainview_frame.add(mainview_sw)
		hpaned.add2(vpaned)

		vpaned1.add1(hpaned)
		self.sub_vbox = gtk.VBox()
		vpaned1.add2(self.sub_vbox)

		self.statusbar = gtk.Statusbar()
		vbox.pack_end(self.statusbar, False)

		# show the window
		win_widget.show_all()
		# keep some widgets
		self.win_widget = win_widget
		self.actiongroup = actiongroup
		self.uimanager = uimanager

		self.maintree_sw = maintree_sw
		self.mainview_sw = mainview_sw

		self.vadjl = self.maintree_sw.get_vadjustment()
		self.vadjl.connect ('value_changed', self.syncnodes, None)

		self.vadjr = self.mainview_sw.get_vadjustment()
		self.vadjr.connect('value_changed', self.syncrcs, None)

		self.update_ui()
		self.statusbar.push(0,_("Not Connected"))

                self.sub_vbox.hide_all()

        def syncnodes(self, widget, data):
                '''
                print widget.value
                print widget.lower
                print widget.upper
                print widget.step_increment
                print widget.page_increment
                print widget.page_size
                '''
                if self.vadjr.upper == self.vadjr.page_size and self.vadjr.upper > widget.upper:
                        return
                if self.vadjr != None:
                        self.vadjr.set_all(widget.value, \
                                widget.lower, widget.upper, \
                                widget.step_increment, widget.page_increment, \
                                widget.page_size)

        def syncrcs(self, widget, data):
                if self.vadjl != None:
                        self.vadjl.set_all(widget.value, \
                                widget.lower, widget.upper, \
                                widget.step_increment, widget.page_increment, \
                                widget.page_size)

        #neoshine begin
	def on_script_generator(self, action):
		script_generatorview(window, manager)
		return

	def on_checkbutton_toggled(self, checkbutton, widget) :
                widget.set_sensitive(checkbutton.get_active())

	def change_group_mode(self, action) :
                self.update()

	def change_maintenance_mode(self, action) :
                if action.get_active() :
			value = "true"
                else :
			value = "false"
		manager.set_crm_attribute("crm_config", "maintenance-mode", value)
                if manager.failed_reason != "" :
                        msgbox(top_window, manager.failed_reason)

	def change_record_pending(self, action) :
                if action.get_active() :
			value = "true"
                else :
			value = "false"
		manager.set_crm_attribute("op_defaults", "record-pending", value)
                if manager.failed_reason != "" :
                        msgbox(top_window, manager.failed_reason)

	def on_upgrade_src(self, action):
		ret = os.popen("ps -ef |grep -v grep |grep corosync |wc -l")
		if '0' in ret.read():
			upgradeview(top_window)
		else:
			msgbox(top_window, _("Please stop NKHA first: ") + "service neokylinha stop")
		return

        def on_register(self, action):
            HALicenseManager(window)
            #They tell me that window is a global variable...

        def on_manual(self, action):
		filename = '@HA_DATADIR@/heartbeat-gui/NeoKylin_HA_Cluster_SoftwareV7.0_Manual.pdf'
                if os.path.exists(filename):
                        ret = os.fork()
                        if ret == 0:
                                if os.path.exists("/usr/bin/evince"):
                                        os.execvp('evince', ['evince', filename])
                else:
                        msgbox(top_window, _("File %s not exist!")%(filename))

        def on_item_move(self, action) :
                if action.get_name() == "uprsc" :
			if self.cur_name in manager.get_top_rsc():
                                self.on_up_group()
			else:
				self.on_up()
                elif action.get_name() == "downrsc" :
			if self.cur_name in manager.get_top_rsc():
				self.on_down_group()
			else:
                                self.on_down()

        def on_up(self) :
                (model, iter) = self.maintree.widget.get_selection().get_selected()
                if not (iter != None and model.get_path(iter)[-1] != 0 ):
                        return

		selected_node = None
                prev_node = None
		primitive_list = manager.xml_nodes["cib"].getElementsByTagName("primitive")
		for primitive in primitive_list:
			if primitive.getAttribute('id') == self.cur_name :
                                selected_node = primitive
                                break

		if selected_node != None:
			parent_node = selected_node.parentNode
			for primitive in parent_node.childNodes:
				if primitive.nodeType != primitive.ELEMENT_NODE :
					continue
				if primitive.getAttribute('id') == self.cur_name :
					break
				prev_node = primitive
		else:
			return

                try :
                        parent_node.insertBefore(selected_node.cloneNode(True), prev_node)
                except :
                        return

                parent_node.removeChild(selected_node)

		if manager.validate_cib() :
                	xml_str = parent_node.toxml().replace("\n", "")
			manager.cib_do_cmd("cib_replace\n%s\n%s"%(str(parent_node.tagName), str(xml_str)))
        	        if manager.failed_reason != "" :
                	        msgbox(top_window, manager.failed_reason)
		self.update()

        def on_up_group(self) :
                parent_node = manager.xml_nodes["cib"].getElementsByTagName("resources")[0]

                group_nodes = []
                for child in parent_node.childNodes :
                                if child.nodeType != child.ELEMENT_NODE :
                                        continue
                                group_nodes.append(child)

                (model, iter) = self.maintree.widget.get_selection().get_selected()
                if not (iter != None and model.get_path(iter)[-1] != 0 ):
                        return

                selected_node = None
                prev_node = None
                i = 0
                while i < len(group_nodes):
                        if group_nodes[i].getAttribute('id') == self.cur_name :
                                selected_node = group_nodes[i]
                                break
                        prev_node = group_nodes[i]
                        i = i + 1

                try :
                        parent_node.insertBefore(selected_node.cloneNode(True), prev_node)
                except :
                        return

                parent_node.removeChild(selected_node)

                if manager.validate_cib() :
                        xml_str = parent_node.toxml().replace("\n", "")
                        manager.cib_do_cmd("cib_replace\n%s\n%s"%(str("resources"), str(xml_str)))
                        if manager.failed_reason != "" :
                                msgbox(top_window, manager.failed_reason)
                self.update()

        def on_down(self) :
                (model, iter) = self.maintree.widget.get_selection().get_selected()
		if not(iter != None and model.iter_next(iter) != None) :
                        return

                selected_node = None
                nn_node = None
                primitive_list = manager.xml_nodes["cib"].getElementsByTagName("primitive")
                for primitive in primitive_list:
                        if primitive.getAttribute('id') == self.cur_name :
                                selected_node = primitive
                                break

		group_nodes = []
                if selected_node != None:
                        parent_node = selected_node.parentNode
			i = 0
                        for primitive in parent_node.getElementsByTagName("primitive"):
				group_nodes.append(primitive)

                        for primitive in group_nodes:
                                if primitive.getAttribute('id') == self.cur_name :
                                        break
                                i = i + 1
                else:
                        return

                if len(group_nodes) <= i+2 :  #nn_iter == None :
                        try :
                                parent_node.appendChild(selected_node.cloneNode(True))
                        except :
                                return
                else :
                        nn_node = group_nodes[i+2]
                        try :
                                parent_node.insertBefore(selected_node.cloneNode(True), nn_node)
                        except :
                                return

                parent_node.removeChild(selected_node)

                if manager.validate_cib() :
                        xml_str = parent_node.toxml().replace("\n", "")
                        manager.cib_do_cmd("cib_replace\n%s\n%s"%(str(parent_node.tagName), str(xml_str)))
                        if manager.failed_reason != "" :
                                msgbox(top_window, manager.failed_reason)
                self.update()

        def on_down_group(self) :
                parent_node = manager.xml_nodes["cib"].getElementsByTagName("resources")[0]
                group_nodes = []
                for child in parent_node.childNodes :
                                if child.nodeType != child.ELEMENT_NODE :
                                        continue
                                group_nodes.append(child)

                (model, iter) = self.maintree.widget.get_selection().get_selected()

                if not(iter != None and model.iter_next(iter) != None) :
                        return

                selected_node = None
                nn_node = None
                i = 0
                while i < len(group_nodes):
                        if group_nodes[i].getAttribute('id')==self.cur_name :
                                selected_node = group_nodes[i]
                                break
                        i = i + 1

                if len(group_nodes) <= i+2 :  #nn_iter == None :
                        try :
                                parent_node.appendChild(selected_node.cloneNode(True))
                        except :
                                return
                else :
                        nn_node = group_nodes[i+2]
                        try :
                                parent_node.insertBefore(selected_node.cloneNode(True), nn_node)
                        except :
                                return
                parent_node.removeChild(selected_node)

                xml_str = parent_node.toxml().replace("\n", "")
                manager.cib_do_cmd("cib_replace\n%s\n%s"%(str("resources"), str(xml_str)))
                if manager.failed_reason != "" :
                        msgbox(top_window, manager.failed_reason)
		self.update()

        def on_add_item(self, action):
		if action.get_name() == "addnode" :
			type = "nodes"
			title = _("Add Nodes")
		elif action.get_name() == "constraint" :
			type = "constraints"
			title = _("Constraints")
		elif action.get_name() == "globalparameter" :
			type = "crm_config"
			title = _("Preferences")

                if self.view_status.get(type) != None :
                        last_show_mode = self.view_status[type][0]
                else :
                        last_show_mode = 0

                if type == "configuration" :
                        self.cur_view = ClusterView()
                elif type == "crm_config" and mode_level == 0 :
                        self.cur_type = "crm_config_simple"
                        self.cur_view = CRMConfigView()
                        if not self.cur_view.update() :
                                return
        	        self.cur_view.widget.set_property("height-request", 300)
	                self.cur_view.widget.set_property("width-request", 500)
                elif type in ["crm_config", "nodes", "constraints", "status", "rsc_defaults", "op_defaults"] \
                                and manager.xml_nodes["cib"].getElementsByTagName(type) != [] :
                        self.cur_view = ObjectView(manager.xml_nodes["cib"].getElementsByTagName(type)[0],
                                        is_topview = True, show_mode = last_show_mode)
                elif type in ["rsc_defaults", "op_defaults"] \
                                and manager.xml_nodes["cib"].getElementsByTagName(type) == [] :
                        self.cur_view = ObjectView(type, is_topview = True, missing_opt_obj_parent_type = "configuration",
                                        show_mode = last_show_mode)
                elif type == "management" :
                        self.cur_view = ManageView()
                else : 
                        self.cur_view = None
                        return 

                global top_window
                dialog = gtk.Dialog(title, top_window, gtk.DIALOG_MODAL,
                        (gtk.STOCK_QUIT, gtk.RESPONSE_CANCEL))
                dialog.set_border_width(5)
                dialog.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_NORMAL)
                #dialog.set_default_response(gtk.RESPONSE_CANCEL)

		dialog.vbox.pack_start(self.cur_view.widget, False, padding = 2)

                save_top_window = top_window
                top_window = dialog
                dialog.show_all()

		while True :
                        ret = dialog.run()
	                if self.view_status.get(self.cur_type) != None :
                	        self.cur_view.restore_status(self.view_status[self.cur_type])
                        if ret in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT]:
                                dialog.destroy()
                                top_window = save_top_window
                                return None

        def on_add_rsc(self, action):
                init_cib_xml_node = manager.xml_nodes["cib"]
                selected_node = self.get_selected_node()
		append_title = ""

                if selected_node == None or selected_node.tagName != "group":
                        selected_node = init_cib_xml_node.getElementsByTagName("resources")[0]
		else:
			append_title = _("Add") + _("Sub-resource For \"%s\"")%self.cur_name

                elem_notebook = ElementNotebook(selected_node, True)
                elem_notebook.update(selected_node)
                elem_notebook.on_add(invoked_by_wizard = True, append_title = append_title)
		return

	def get_selected_node(self):
                (model, iter) = self.maintree.widget.get_selection().get_selected()
                if iter == None :
                        return
		try:
			real_rsc_id = self.cur_name.split(":")[0]
		except:
			real_rsc_id = ""

		if self.cur_type == _("primitive"):
			type = "primitive"
		elif self.cur_type == _("group"):
			type = "group"
		elif self.cur_type == _("clone"):
			type = "clone"
		elif self.cur_type == _("master"):
			type = "master"
		else:
			type = self.cur_type

		xml_node = manager.xml_nodes["cib"].getElementsByTagName(type)
		for node in xml_node:
			if node.getAttribute('id') == real_rsc_id:
				return node

		return None

        def on_del_item(self, action):
                selected_node = self.get_selected_node()
                if selected_node == None :
                        return

                ret = confirmbox(top_window, _("This will delete the %s \"%s\"")%(_(name_cap(selected_node.tagName)), selected_node.getAttribute("id")) 
				+ _("and related constraints.\n"),
                                (gtk.STOCK_NO, gtk.RESPONSE_NO, gtk.STOCK_YES, gtk.RESPONSE_YES),
                                _("Delete the selected object?"))
                if ret == gtk.RESPONSE_YES :
			self.del_res(selected_node, False)

	def get_top_parent_rsc(self, rsc_xml):
		rsc = rsc_xml.getAttribute('id')
		if rsc in manager.get_top_rsc():
			return rsc_xml
		parent_node = rsc_xml.parentNode
		parent_id = parent_node.getAttribute('id')
		if len(manager.get_sub_rsc(str(parent_id))) == 1:
			return self.get_top_parent_rsc(parent_node)
		else:
			return parent_node

	def del_res(self, selected_node, del_group=True):
                	#deled_resource = selected_node.getAttribute("id")
			#print deled_resource
	                #try :
        	        parent = selected_node.parentNode.getAttribute('id')
                	if len(manager.get_sub_rsc(str(parent))) == 1 :
				if del_group:
					#selected_node = selected_node.parentNode
					selected_node = self.get_top_parent_rsc(selected_node)
				else:
                  	      		msgbox(top_window, _("Group must retain at least a resource!"))
                        		return 1
			#except:
			#	pass
			del_drbd = False
			if selected_node.getAttribute('type') == "drbd":
				selected_node = self.get_top_parent_rsc(selected_node)
				del_drbd = True
			elif manager.get_rsc_type(selected_node.getAttribute('id')) in ["master"]:
				for primitive in selected_node.getElementsByTagName("primitive"):
					if primitive.getAttribute('type') == "drbd":
						del_drbd = True
						break

			if del_drbd:
				manager.cib_do_cmd("cib_replace\ndrbd_split\n%s"%(str("<drbd_split/>")))
				if manager.failed_reason != "" :
		                        msgbox(top_window, manager.failed_reason)
					return 1

	                rsc_locations = [] 
        	        for rsc_location in manager.xml_nodes["cib"].getElementsByTagName("rsc_location") :
				if rsc_location.getAttribute('rsc') == selected_node.getAttribute("id"):
        	                	rsc_locations.append(rsc_location)

	                rsc_colocations = [] 
        	        for rsc_colocation in manager.xml_nodes["cib"].getElementsByTagName("rsc_colocation") :
				if rsc_colocation.getAttribute('rsc') == selected_node.getAttribute("id") or rsc_colocation.getAttribute('with-rsc') == selected_node.getAttribute("id"):
        	                	rsc_colocations.append(rsc_colocation)

	                rsc_orders = [] 
        	        for rsc_order in manager.xml_nodes["cib"].getElementsByTagName("rsc_order") :
				if rsc_order.getAttribute('first') == selected_node.getAttribute("id") or rsc_order.getAttribute('then') == selected_node.getAttribute("id"):
        	                	rsc_orders.append(rsc_order)

        	        for location in rsc_locations :
                		xml_str = location.toxml().replace("\n", "")
	                       	manager.cib_do_cmd("cib_delete\nconstraints\n%s"%(str(xml_str)))

        	        for colocation in rsc_colocations :
                		xml_str = colocation.toxml().replace("\n", "")
	                       	manager.cib_do_cmd("cib_delete\nconstraints\n%s"%(str(xml_str)))

        	        for order in rsc_orders :
                		xml_str = order.toxml().replace("\n", "")
	                       	manager.cib_do_cmd("cib_delete\nconstraints\n%s"%(str(xml_str)))

                        #selected_node.parentNode.removeChild(selected_node)
                        if manager.validate_cib() :
				#############################cleanup the deleted resource
				rsc_id = selected_node.getAttribute("id")
                        	cleanup_rscs = []
			        if manager.get_rsc_type(rsc_id) != "primitive" :
                        	        all_subrscs = manager.get_all_subrsc(rsc_id)
			                if all_subrscs == None :
                        	                return
			                for rsc in all_subrscs :
                        	                if manager.get_rsc_type(rsc) == "primitive" :
                                       			cleanup_rscs.append(rsc)
			        else :
                        	        cleanup_rscs.append(rsc_id)
				#################end

                        	xml_str = selected_node.toxml().replace("\n", "")
                                #manager.cib_do_cmd("cib_delete\n%s\n%s"%(str(selected_node.tagName), str(xml_str)))
                                manager.cib_do_cmd("cib_delete\n%s\n%s"%(str("resources"), str(xml_str)))
                                if manager.failed_reason != "" :
                                        msgbox(top_window, selected_node.getAttribute("id")+":"+manager.failed_reason)
                                        if manager.active_cib != "" :
                                        	manager.set_update()
					return 1
				else:#############################cleanup the deleted resource
			                for rsc in cleanup_rscs :
                        		        manager.do_cmd("crm_rsc_cmd\n%s\ncleanup\n"%(str(rsc)))
				#################end
                                manager.set_update()
                	return 0

        def on_rsc_attr(self, action) :
                init_cib_xml_node = manager.xml_nodes["cib"]

                selected_node = self.get_selected_node()
                if selected_node == None :
                        return

                objdlg = ObjectViewDlg(selected_node, False)
                while True :
                        new_xml_node = objdlg.run()
                        if new_xml_node == None :
                                if window.cur_view != None :
                                	window.cur_view.update()
                                return

                        if not manager.validate_cib(init_cib_xml_node) :
                                continue
                        xml_str = init_cib_xml_node.getElementsByTagName("resources")[0].toxml().replace("\n", "")

                        manager.cib_do_cmd("cib_replace\n%s\n%s"%(str("resources"), str(xml_str)))
                        if manager.failed_reason != "" :
                                msgbox(top_window, manager.failed_reason)
                        else :
                                if window.cur_view != None :
                                        window.cur_view.update()
                                objdlg.destroy()
	                        return

        def on_intellect_switch(self, action):
                #switchview(top_window, manager)
		#IntelligentManager(top_window)
                return

	def on_mirror(self, action):
		mirror_and_recoveryview()
		return

	def on_qudisk(self, action):
		qudiskview(top_window, manager)

	#add by zxj
	def on_gfs(self,action):
		gfsview(top_window, manager)

        def on_main_node(self, action) :
                selected_node = self.get_selected_node()
                if selected_node == None :
                        return
                mainnodeview(selected_node)

	def on_add_nethb(self, action) :
		addnethbview(window, manager)

        def on_add_serialhb(self, action) :
                addserialhbview(window, manager)
        
        def on_add_diskhb(self, action) :
                adddiskhbview(top_window, manager)


        def on_drbd(self,action):
		drbdview()
		return

        def on_rapid_deploy(self, action):
		importview(top_window, manager)
		return

        def on_item_alarm(self, action):
		alarmview(top_window, manager)

        def on_item_sfex(self, action):
                sfexview()

	def change_child_id(self, xml_node, parent_id, new_id, uuid = False):
		for child in xml_node.childNodes:
			if child.nodeType != xml.dom.Node.ELEMENT_NODE :
				continue
			id = child.getAttribute('id')
			if id.count(parent_id + "-") > 0 :
				child.setAttribute('id', id.replace(parent_id + "-", new_id + "-"))
			elif uuid:
				child.setAttribute('id', gen_uuid())
			self.change_child_id(child, parent_id, new_id, uuid)
		return

	def change_self_id(self, xml_node, old_id, new_id, uuid = False):
		if xml_node.getAttribute('id').count(old_id + "-") > 0 :
			xml_node.setAttribute('id', xml_node.getAttribute('id').replace(old_id + "-", new_id + "-"))
		elif uuid :
			xml_node.setAttribute('id', new_id + gen_uuid())
		return

	def on_move_to_group(self, action):
		moved_resource = self.cur_name
		try :    
                	parent = manager.parent[moved_resource]
                except KeyError :
                        parent = moved_resource
                if len(manager.get_sub_rsc(parent)) == 1 :
			msgbox(top_window, _("Group must retain at least a resource!"))
			return

		store = []
                group_list = manager.get_top_rsc()
                if group_list == None :
                        return
		for rsc in group_list:
			if manager.get_rsc_type(rsc) == "group" :
                                store.append(rsc)

                store.insert(0, _("OUTGROUP"))

                move = kvbox(_("Move To Group"), None,
				[Field("group", _("Move To"), _("OUTGROUP"), store, False, entry_editable = False)])
		if move != None:
                        ret = confirmbox(top_window, _("Move into or out of group will restart the resource or resources \nin the group which running!\n\n")
                                        + _("This will move the resource %s to %s")%(moved_resource, move["group"]),
                                        (gtk.STOCK_YES, gtk.RESPONSE_YES, gtk.STOCK_NO, gtk.RESPONSE_NO),
                                        _("Move To Group"))
                        if ret == gtk.RESPONSE_NO :
                                        return

			if move["group"] == _("OUTGROUP") : #out group
				if validate_type == "dtd" :
                                        attr_name = "target_role"
                                else :  
                                        attr_name = "target-role"

				target_role_value = manager.do_cmd("get_rsc_attr\n%s\nmeta\n%s"%(moved_resource, attr_name))

				resource_list = manager.xml_nodes["cib"].getElementsByTagName("primitive")
				for rsc in resource_list :
                		        if rsc.getAttribute('id') == moved_resource :
                                		selected_resource = rsc
						parent_group = rsc.parentNode
                                		break

		                try :
					new_resource = selected_resource.cloneNode(True)
                		        parent_group.parentNode.insertBefore(new_resource, parent_group)
		                except :
                		        return

                                parent_group.removeChild(selected_resource)
                                xml_str = parent_group.parentNode.toxml().replace("\n", "")
                                manager.cib_do_cmd("cib_replace\n%s\n%s"%(str(parent_group.parentNode.tagName), str(xml_str)))
                                if manager.failed_reason != "" :
                                        msgbox(top_window, manager.failed_reason)

				if not (target_role_value == None or len(target_role_value) == 0) :
                                        manager.do_cmd("set_rsc_attr\n%s\nmeta\n%s\n%s"%(moved_resource, attr_name, target_role_value[0]))
                                        if manager.failed_reason != "" :
                                                        msgbox(top_window, manager.failed_reason)

                                xml_constraints = manager.xml_nodes["cib"].getElementsByTagName("constraints")[0]
                                location_list = xml_constraints.getElementsByTagName("rsc_location")
                                order_list = xml_constraints.getElementsByTagName("rsc_order")
                                colocation_list = xml_constraints.getElementsByTagName("rsc_colocation")

				parent_id = parent_group.getAttribute('id')

                                for location in location_list :
                                        if location.getAttribute('rsc') == parent_id :
						new_location = location.cloneNode(True)
						self.change_self_id(new_location, parent_id, moved_resource, True)
                                                new_location.setAttribute('rsc', moved_resource)
						self.change_child_id(new_location, parent_id, moved_resource, True)
						xml_constraints.appendChild(new_location)
                                for order in order_list :
                                        if order.getAttribute('first') == parent_id or order.getAttribute('then') == parent_id :
                                                new_order = order.cloneNode(True)
						self.change_self_id(new_order, parent_id, moved_resource, True)
						if order.getAttribute('first') == parent_id:
	                                                new_order.setAttribute('first', moved_resource)
                                                if order.getAttribute('then') == parent_id:
                                                        new_order.setAttribute('then', moved_resource)
						self.change_child_id(new_order, parent_id, moved_resource, True)
                                                xml_constraints.appendChild(new_order)
                                for colocation in colocation_list :
                                        if colocation.getAttribute('rsc') == parent_id or colocation.getAttribute('with-rsc') == parent_id :
						new_colocation = colocation.cloneNode(True)
						self.change_self_id(new_colocation, parent_id, moved_resource, True)
                                                if colocation.getAttribute('rsc') == parent_id:
                                                        new_colocation.setAttribute('rsc', moved_resource)
                                                if colocation.getAttribute('with-rsc') == parent_id:
                                                        new_colocation.setAttribute('with-rsc', moved_resource)
						self.change_child_id(new_colocation, parent_id, moved_resource, True)
						xml_constraints.appendChild(new_colocation)

				xml_str = xml_constraints.toxml().replace("\n", "")
				manager.cib_do_cmd("cib_replace\n%s\n%s"%(str("constraints"), str(xml_str)))
		                if manager.failed_reason != "" :
                		        msgbox(top_window, manager.failed_reason)

			else : #into other group
				parent_group = None
				parent_node = manager.xml_nodes["cib"].getElementsByTagName("resources")[0]
                                group_list = parent_node.getElementsByTagName("group")

				for group in group_list :
                                        resource_list = group.getElementsByTagName("primitive")
                                        for res in resource_list :
                                                if res.getAttribute('id') == moved_resource :
                                                        selected_resource = res
                                                        parent_group = group
                                                        break
					if group.getAttribute('id') == move["group"] :
						to_group = group

				if parent_group == None :
					resource_list = parent_node.getElementsByTagName("primitive")
					parent_group = parent_node
					for res in resource_list :
						if res.getAttribute('id') == moved_resource :
                                                        selected_resource = res
                                                        break

				xml_constraints = manager.xml_nodes["cib"].getElementsByTagName("constraints")[0]
                                location_list = xml_constraints.getElementsByTagName("rsc_location")
                                order_list = xml_constraints.getElementsByTagName("rsc_order")
                                colocation_list = xml_constraints.getElementsByTagName("rsc_colocation")
                                for location in location_list :
                                        if location.getAttribute('rsc') == moved_resource :
						xml_constraints.removeChild(location)
						#manager.do_cmd(str("del_co\nrsc_location\n"+location.getAttribute("id")))
                                for order in order_list :
                                        if order.getAttribute('first') == moved_resource or order.getAttribute('then') == moved_resource :
						#manager.do_cmd(str("del_co\nrsc_order\n"+order.getAttribute("id")))
						xml_constraints.removeChild(order)
                                for colocation in colocation_list :
                                        if colocation.getAttribute('rsc') == moved_resource or colocation.getAttribute('with-rsc') == moved_resource :
						#manager.do_cmd(str("del_co\nrsc_colocation\n"+colocation.getAttribute("id")))
						xml_constraints.removeChild(colocation)

                                xml_str = xml_constraints.toxml().replace("\n", "")
                                manager.cib_do_cmd("cib_replace\n%s\n%s"%(str("constraints"), str(xml_str)))
                                if manager.failed_reason != "" :
                                        msgbox(top_window, manager.failed_reason)

				if parent_group.getAttribute('id') != move["group"]:
                                	try :
                                        	to_group.appendChild(selected_resource.cloneNode(True))
                                	except :
                                        	return

                                	parent_group.removeChild(selected_resource)
					xml_str = parent_node.toxml().replace("\n", "")
					manager.cib_do_cmd("cib_replace\n%s\n%s"%(str("resources"), str(xml_str)))
                        	        if manager.failed_reason != "" :
                	                        msgbox(top_window, manager.failed_reason)


        def on_rename(self, action) :
                rename = kvbox(_("Rename Resource"), None,
                                [Field("name", _("Rename %s As")%(self.cur_name), self.cur_name, [], entry_editable = True)])
                if rename != None:

                        if self.cur_type in [_("primitive")]:
                                if manager.rsc_exists(rename["name"]) :
                                        msgbox(top_window, _("the ID already exists"))
                                        self.on_rename(action)
                                        return
                        else:
                                if manager.rsc_exists(rename["name"]) and manager.get_rsc_type(rename["name"]) != "group":
                                        msgbox(top_window, _("the Group Name is exists"))
                                        self.on_rename(action)
                                        return

                        if re.match('^\w+$', rename["name"])is None :
                                msgbox(top_window, _("The name is not right, please input it again!"))
                                self.on_rename(action)
                                return

                        ret = confirmbox(top_window, _("Rename will restart the resource or resources in the group which running!\n\n")
                                        + _("This will rename the %s: %s to %s")%(self.cur_type, self.cur_name, rename["name"]),
                                        (gtk.STOCK_YES, gtk.RESPONSE_YES, gtk.STOCK_NO, gtk.RESPONSE_NO),
                                        _("Rename Resource"))
                        if ret == gtk.RESPONSE_NO :
                                        return
                        cib_resource_org = manager.xml_nodes["cib"].getElementsByTagName("resources")[0]
                        cib_constraints_org = manager.xml_nodes["cib"].getElementsByTagName("constraints")[0]
			cib_resource = cib_resource_org.cloneNode(True)
			cib_constraints = cib_constraints_org.cloneNode(True)

                        if self.cur_type in [_("primitive")]:
                                resource_list = cib_resource.getElementsByTagName("primitive")
                                for res in resource_list :
                                        if res.getAttribute('id') == self.cur_name :
                                                res.setAttribute('id', rename["name"])
                                                for instance_attribute in res.getElementsByTagName('instance_attributes'):
                                                        m = re.match('^('+self.cur_name+')(.*)$', instance_attribute.getAttribute('id'))
                                                        if m != None:
                                                                instance_attribute.setAttribute('id', rename["name"] + m.group(2))

                                                for meta_attribute in res.getElementsByTagName('meta_attributes'):
                                                        m = re.match('^('+self.cur_name+')(.*)$', meta_attribute.getAttribute('id'))
                                                        if m != None:
                                                                meta_attribute.setAttribute('id', rename["name"] + m.group(2))
                                                        for nvpair in meta_attribute.getElementsByTagName('nvpair'):
                                                                m = re.match('^('+self.cur_name+')(.*)$', nvpair.getAttribute('id'))
                                                                if m != None:
                                                                        nvpair.setAttribute('id', rename["name"] + m.group(2))



                                lrm_resource_list = cib_resource.getElementsByTagName("lrm_resource")
                                for res in lrm_resource_list :
                                        if res.getAttribute('id') == self.cur_name :
                                                res.setAttribute('id', rename["name"])
                        else:
                                group_list = cib_resource.getElementsByTagName("group")
                                for group in group_list :
                                        if group.getAttribute('id') == self.cur_name :
                                                group.setAttribute('id', rename["name"])
                                                for meta_attribute in group.getElementsByTagName('meta_attributes'):
                                                        m = re.match('^('+self.cur_name+')(.*)$', meta_attribute.getAttribute('id'))
                                                        if m != None:
                                                                meta_attribute.setAttribute('id', rename["name"] + m.group(2))
                                                        for nvpair in meta_attribute.getElementsByTagName('nvpair'):
                                                                m = re.match('^('+self.cur_name+')(.*)$', nvpair.getAttribute('id'))
                                                                if m != None:
                                                                        nvpair.setAttribute('id', rename["name"] + m.group(2))
                                                break

                        location_list = cib_constraints.getElementsByTagName("rsc_location")
                        order_list = cib_constraints.getElementsByTagName("rsc_order")
                        colocation_list = cib_constraints.getElementsByTagName("rsc_colocation")
                        for location in location_list :
                                if location.getAttribute('rsc') == self.cur_name :
                                        location.setAttribute('rsc', rename["name"])
					self.change_self_id(location, self.cur_name, rename["name"])
                                        self.change_child_id(location, self.cur_name, rename["name"])

                        for order in order_list :
                                if order.getAttribute('first') == self.cur_name :
                                        order.setAttribute('first', rename["name"])
                                if order.getAttribute('then') == self.cur_name :
                                        order.setAttribute('then', rename["name"])
				self.change_self_id(order, self.cur_name, rename["name"])
                                self.change_child_id(order, self.cur_name, rename["name"])
                        for colocation in colocation_list :
                                if colocation.getAttribute('rsc') == self.cur_name :
                                        colocation.setAttribute('rsc', rename["name"])
                                if colocation.getAttribute('with-rsc') == self.cur_name :
                                        colocation.setAttribute('with-rsc', rename["name"])
				self.change_self_id(colocation, self.cur_name, rename["name"])
                                self.change_child_id(colocation, self.cur_name, rename["name"])

			cib_resource_org.parentNode.replaceChild(cib_resource, cib_resource_org)
			cib_constraints_org.parentNode.replaceChild(cib_constraints, cib_constraints_org)

                        xml_str = cib_resource.parentNode.toxml().replace("\n", "")
                        manager.cib_do_cmd("cib_replace\n%s\n%s"%(str(cib_resource.parentNode.tagName), str(xml_str)))
                        if manager.failed_reason != "" :
                                msgbox(top_window, manager.failed_reason)
        #neoshine end

	#neoshineha ming.liu
        def on_rsc_action(self, action) :
                (cur_type, cur_name) = self.manage_tree.get_selected_node()
                if action.get_name() == "startrsc" :
                        target_role = "Started"
                elif action.get_name() == "stoprsc" :
			if confirmbox(top_window, _("Do you want to stop the resource?"))  != gtk.RESPONSE_YES :
				return

                        target_role = "Stopped"
                else :
                        target_role = "#default"

                if validate_type == "dtd" :
                        metaattr_name = "target_role"
                else :
                        metaattr_name = "target-role"

		real_rsc_id = cur_name.split(":")[0]

                rsc_xml = None
                for resources_node in manager.xml_nodes["cib"].cloneNode(True).getElementsByTagName("resources") :
			if cur_type in [_("primitive")]:
				type = "primitive"
			elif cur_type in [_("group")]:
				type = "group"
			elif cur_type in [_("clone")]:
				type = "clone"
			elif cur_type in [_("master")]:
				type = "master"
			else :
				type = cur_type

                        for rsc_node in resources_node.getElementsByTagName(type) :
                                if rsc_node.getAttribute("id") == real_rsc_id :
                                        rsc_xml = rsc_node
                                        break
 
                if rsc_xml == None : 
                        msgbox(top_window, _("Cannot find the %s: %s")%(cur_type, real_rsc_id))
                        return
 
                supported_rsc_types = manager.get_supported_rsc_types()
 
                found_nv = False
                clear_all = False
                for nv_xml_node in rsc_xml.getElementsByTagName("nvpair") :
                        if nv_xml_node.getAttribute("name") != metaattr_name :
                                continue

			target_rsc = nv_xml_node
                        while target_rsc.tagName not in supported_rsc_types :
                                target_rsc = target_rsc.parentNode
 
                        target_rsc_id = target_rsc.getAttribute("id")
                        current_value = nv_xml_node.getAttribute("value")
                       
                        if target_rsc_id == real_rsc_id :
                                found_nv = True
                                if target_role == "#default" :
                                        nv_xml_node.parentNode.removeChild(nv_xml_node)
                                else :
                                        nv_xml_node.setAttribute("value", target_role)
                        else :
				if current_value == target_role :
					continue
                                if not clear_all :
                                        retval = confirmbox(top_window, _("Caused by your previous action, this attribute has been set to \"")
                                                +current_value
                                                +_("\".")+"\n\n"
                                                +_("Recommended") + _(":")+"\n"
                                                +_("Select \"Clear All\" to remove the attributes for all of the sub-resources.")+"\n"
                                                +_("All of the sub-resources will inherit the attributes from their parent."),
                                                (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
						gtk.STOCK_NO, gtk.RESPONSE_NO,
                                                gtk.STOCK_CLEAR, gtk.RESPONSE_OK,
                                                "Clear All", gtk.RESPONSE_YES),
                                                _("Clear the %s=\"%s\" attribute for sub-resource \"")%(metaattr_name, current_value)
                                                +target_rsc_id+_("\"?"))
                                        if retval in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT] :
                                                return  

                                        if retval in [gtk.RESPONSE_OK, gtk.RESPONSE_YES] :
                                                nv_xml_node.parentNode.removeChild(nv_xml_node)
 
                                        if retval == gtk.RESPONSE_YES :
                                                clear_all = True
                                else :
                                        nv_xml_node.parentNode.removeChild(nv_xml_node)

                if not found_nv and target_role != "#default" :
                        (parent_xml_node, add_obj_type, new_mid_elem) = manager.real_add_obj_type(rsc_xml, "meta_attributes", True)
                        if parent_xml_node == None :
                                msgbox(top_window, _("Cannot %s %s: XML processing error")%(target_role, real_rsc_id))
                                return
 
                        impl = getDOMImplementation()
                        newdoc = impl.createDocument(None, "nvpair", None)
                        nv = newdoc.documentElement
                        parent_xml_node.appendChild(nv)
                        attr_id = manager.auto_unique_id(nv, metaattr_name)
                        nv.setAttribute("id", attr_id)
                        nv.setAttribute("name", metaattr_name)
                        nv.setAttribute("value", target_role)
 
                xml_str = rsc_xml.toxml().replace("\n", "")
                manager.cib_do_cmd("cib_replace\n%s\n%s"%(str(rsc_xml.tagName), str(xml_str)))
                if manager.failed_reason != "" :
                       msgbox(top_window, manager.failed_reason)


        def on_rsc_cleanup(self, action) :
                (cur_type, cur_name) = self.manage_tree.get_selected_node()
                rsc_list = manager.get_all_rsc()
                if rsc_list == None :
                        return
                rsc_options = rsc_list[:]
                rsc_options.insert(0, _("all resources"))

                node_list = manager.get_normal_nodes()
                if node_list == None :
                        return
                node_options = node_list[:]
                node_options.insert(0, _("all nodes"))

                cleanup = kvbox(_("Cleanup Resource"), None,
                                [Field("rsc", _("Resource"), cur_name, rsc_options, False, entry_editable = False),
                                Field("node", _("Node"), _("all nodes"), node_options, False, entry_editable = False)])

                if cleanup != None :
                        cleanup_rscs = []
                        if cleanup["rsc"] == _("all resources") :
                                for rsc in rsc_list :
                                        if manager.get_rsc_type(rsc) == "primitive" :
                                                cleanup_rscs.append(rsc)
                        elif manager.get_rsc_type(cleanup["rsc"]) != "primitive" :
                                all_subrscs = manager.get_all_subrsc(cleanup["rsc"])
                                if all_subrscs == None :
                                        return
                                for rsc in all_subrscs :
                                        if manager.get_rsc_type(rsc) == "primitive" :
                                                cleanup_rscs.append(rsc)
                        else :
                                cleanup_rscs.append(cleanup["rsc"])

                        if cleanup["node"] == _("all nodes") :
                                cleanup_nodes = ''
                        else :
                                cleanup_nodes = cleanup["node"]

                        for rsc in cleanup_rscs :
				manager.do_cmd("crm_rsc_cmd\n%s\ncleanup\n%s"%(rsc, cleanup_nodes))

	def on_migrate_time_toggled(self, widget) :
		if widget.get_active():
	                self.duration_hbox.set_sensitive(widget.get_active())
			self.on_duration_toggled(self.radiobuttons["duration"])
                	self.special_time_hbox.set_sensitive(widget.get_active())
			self.on_spe_time_toggled(self.radiobuttons["special time"])
		else:
			self.duration_hbox.set_sensitive(False)
                        self.period_hbox.set_sensitive(False)
	                self.ptime_hbox.set_sensitive(False)
                        self.special_time_hbox.set_sensitive(False)
			self.special_migrate_time_hbox.set_sensitive(False)

        def on_duration_toggled(self, widget) :
                 self.period_hbox.set_sensitive(widget.get_active())
                 self.ptime_hbox.set_sensitive(widget.get_active())

        def on_spe_time_toggled(self, widget) :
                self.special_migrate_time_hbox.set_sensitive(widget.get_active())

        def on_migrate_rsc(self, action) :
                global top_window
                (cur_type, cur_name) = self.manage_tree.get_selected_node()

                dialog = gtk.Dialog(_("Migrate Resource"), top_window, gtk.DIALOG_MODAL,
                        (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK))
                dialog.set_border_width(5)
                dialog.set_default_response(gtk.RESPONSE_OK)

                duration_elems = ["yrs", "mths", "wks", "days", "hrs", "mins", "secs"]
		time_elems = ["year", "month", "day", "hour"]

                combos = {}
                checkbuttons = {}
		self.radiobuttons = {}
                spinbuttons = {}
                name_labels = []
                name_label_max_len = 0
                for key in ["rsc", "to_node", "force", "migrate time", "duration", "period", "period time", "special time", "special migrate time"] :
                        hbox = gtk.HBox()
                        if key in ["rsc", "to_node"] :
                                name_label = gtk.Label(_(name_cap(key))+_(":"))
                                name_label.set_alignment(0, 0.5)
                                name_labels.append(name_label)

                                name_label_len = name_label.size_request()[0]
                                if name_label_len >  name_label_max_len :
                                        name_label_max_len = name_label_len

                                hbox.pack_start(name_label, False, padding=2)

                        if key == "rsc" :
                                widget = gtk.combo_box_new_text()
                                for rsc in manager.get_all_real_rsc() :
                                        widget.append_text(rsc)

                                model = widget.get_model()
                                iter = model.get_iter_first()
                                while iter != None :
                                        if model.get_value(iter,0) == manager.obj_real_id(cur_name) :
                                                widget.set_active_iter(iter)
                                                break
                                        iter = model.iter_next(iter)

                                combos[key] = widget
                                hbox.pack_start(widget, True, padding=2)
                        elif key == "to_node" :
                                widget = gtk.combo_box_new_text()
                                node_list = manager.get_normal_nodes()
                                node_options = node_list[:]
                                node_options.insert(0, "")
                                for node in node_options :
                                        widget.append_text(node)

                                combos[key] = widget
                                hbox.pack_start(widget, True, padding=2)
                        elif key == "force" :
                                widget = gtk.CheckButton(_(name_cap(key)))

                                checkbuttons[key] = widget
                                hbox.pack_start(widget, True, padding=2)
			elif key == "migrate time":
                                widget = gtk.CheckButton(_(name_cap(key)))
                                checkbuttons[key] = widget
                                hbox.pack_start(widget, True, padding=2)
				widget.connect("toggled", self.on_migrate_time_toggled)
                        elif key == "duration" :
                                widget = gtk.RadioButton(None, _(name_cap(key)))
                                self.radiobuttons[key] = widget
                                hbox.pack_start(widget, True, padding=2)
				hbox.set_sensitive(False)
                                self.duration_hbox = hbox

                                widget.connect("toggled", self.on_duration_toggled)


                        elif key == "period" :
                                for key in duration_elems[:4] :
                                        adj = gtk.Adjustment(0, 00, 99, 1, 3)
                                        widget = gtk.SpinButton(adj, 0, 0)
                                        widget.set_width_chars(2)
                                        widget.set_wrap(True)
                                        hbox.pack_start(widget, False)
                                        spinbuttons[key] = widget

                                        label = gtk.Label(_(name_cap(key)) + " ")
                                        hbox.pack_start(label, False, padding=2)
                                        hbox.set_sensitive(False)
                                        self.period_hbox = hbox

                        elif key =="period time" :
                                for key in duration_elems[4:] :
                                        adj = gtk.Adjustment(0, 00, 99, 1, 5)
                                        widget = gtk.SpinButton(adj, 0, 0)
                                        widget.set_width_chars(2)
                                        widget.set_wrap(True)
                                        hbox.pack_start(widget, False)
                                        spinbuttons[key] = widget

                                        label = gtk.Label(_(name_cap(key)) + " ")
                                        hbox.pack_start(label, False, padding=2)
                                        hbox.set_sensitive(False)
                                        self.ptime_hbox = hbox
			elif key == "special time":
                                widget = gtk.RadioButton(self.radiobuttons["duration"], _(name_cap(key)))
                                self.radiobuttons[key] = widget

                                hbox.pack_start(widget, True, padding=2)
                                hbox.set_sensitive(False)
                                self.special_time_hbox = hbox

                                widget.connect("toggled", self.on_spe_time_toggled)

			else:
                                #for key in time_elems[2:] :
					#if key == "year":
	                                 #       adj = gtk.Adjustment(0, 00, 99, 1, 5)
					#elif key == "month":
	                                 #       adj = gtk.Adjustment(0, 00, 12, 1, 5)
					#if key == "day":
	                                 #       adj = gtk.Adjustment(0, 00, 31, 1, 5)
				mig_time_org = time.time()
                		mig_time= time.localtime(mig_time_org)
                		datetime = DateTime(mig_time)
				datetime.time_hr.set_editable(False)
				datetime.time_hrcolon.destroy()
				#datetime.time_hr.destroy()
				datetime.time_min.destroy()
				datetime.time_mincolon.destroy()
				datetime.time_sec.destroy()
				#datetime.time_colon.destroy()
				hbox.pack_start(datetime.time_hbox, False)
                                        	#spinbuttons[key] = datetime.time_date
					#else:#"hour"]
	                                        #adj = gtk.Adjustment(0, 00, 24, 1, 5)
                                        	#widget = gtk.SpinButton(adj, 0, 0)
                                        	#widget.set_width_chars(2)
                                        	#widget.set_wrap(True)
                                        	#hbox.pack_start(widget, False)
                                        	#spinbuttons[key] = widget

                                label = gtk.Label(_(name_cap("hour")) + " ")
                                hbox.pack_start(label, False, padding=2)
                                hbox.set_sensitive(False)
                                self.special_migrate_time_hbox = hbox

				move_time_de_org = datetime.get_date()
				move_time_hr_org = datetime.time_hr.get_text()

                        dialog.vbox.pack_start(hbox, False, padding=2)

                for name_label in name_labels :
                        name_label.set_size_request(name_label_max_len, -1)

                widgets = {}
                widgets["combos"] = combos
                widgets["checkbuttons"] = checkbuttons
                widgets["spinbuttons"] = spinbuttons
		widgets["radiobuttons"] = self.radiobuttons

                widget_group = WidgetGroup(widgets)

                save_top_window = top_window
                top_window = dialog
                dialog.show_all()
                ret = dialog.run()
                if ret in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT] :
                        top_window = save_top_window
                        dialog.destroy()
                        return

                migrate = widget_group.get_values()
		if self.special_migrate_time_hbox.get_property("sensitive") :
			move_time_de = datetime.time_date.get_text()
			move_time_hr = datetime.time_hr.get_text()

                top_window = save_top_window
                dialog.destroy()

                period = ""
                if self.period_hbox.get_property("sensitive") :
                        for key in duration_elems[:4] :
                                if migrate.get(key, "0.0") != "0.0" :
                                        period += migrate[key].split(".")[0] + key[0].upper()
                ptime = ""
                if self.ptime_hbox.get_property("sensitive") :
                        for key in duration_elems[4:] :
                                if migrate.get(key, "0.0") != "0.0" :
                                        ptime += migrate[key].split(".")[0] + key[0].upper()

                if period == "" and ptime == "" :
                        duration = ""
                else :
                        duration = "P" + period
                        if ptime != "" :
                                duration += "T" + ptime
		move_time = ""
		if self.special_migrate_time_hbox.get_property("sensitive") :
			m = re.match('^\d\d\d\d-\d\d-\d\d$', move_time_de)
                	if m is None:
                        	msgbox(top_window, _("Please input the date of migrate!"))
                        	return
                	m = re.match('^(\d+)$', move_time_hr)
                	if m is None or int(m.groups()[0])>23:
                        	msgbox(top_window, _("Please input the hour of migrate! It should between 0 and 23"))
                        	return
			if move_time_de <= str(move_time_de_org) :
                                move_time_de = str(move_time_de_org)
			move_time = move_time_de + "T"  
			if len(move_time_hr)==1:
				move_time = move_time + "0"
			move_time = move_time + move_time_hr + ":00:00"	
			'''move_time = str(int(migrate["year"].split(".")[0]) + 2000)
                        move_time = move_time + "-" 
			if len(migrate["month"].split(".")[0])==1:
				move_time = move_time + "0"
                        move_time = move_time + migrate["month"].split(".")[0]

                        move_time = move_time + "-" 
			if len(migrate["day"].split(".")[0])==1:
				move_time = move_time + "0"
                        move_time = move_time + migrate["day"].split(".")[0]
			if move_time <= str(datetime.date.today()) :
				move_time = str(datetime.date.today())

                        move_time = move_time + "T" 
			if len(migrate["hour"].split(".")[0])==1:
				move_time = move_time + "0"
			move_time = move_time + migrate["hour"].split(".")[0] + ":00:00"'''

                manager.do_cmd("migrate\n%s\n%s\n%s\n%s\n%s"
                                %(migrate.get("rsc", ""), migrate.get("to_node", ""), migrate.get("force", ""), duration, move_time))

                if manager.failed_reason != "" :
			msg = manager.failed_reason.replace("This message can be disabled with -Q", "").replace \
                                ("using the 'crm_resource -U' command or manually with cibadmin", "by \"Clear Migrate Constraints\"")
			msg = manager.failed_reason.replace("Please refer to http://en.wikipedia.org/wiki/ISO_8601#Dates for examples of valid dates\nError performing operation: Invalid argument", "Please input again")
			replace_msgs = ["until the constraint is removed by \"Clear Migrate Constraints\"", 
					"is active on more than one node, returning the default value for", \
					"Resource", "not found", "We can only process primitive resources, not", \
					"Please supply a hostname with -H", "has no type!  Aborting...", "has no class!  Aborting...", \
					"Invalid duration specified:", \
					"Please refer to http://en.wikipedia.org/wiki/ISO_8601#Duration for examples of valid durations",\
					"Invalid date specified:",\
					"Please input again",\
					"\tThis will prevent", "from running on", \
					"until the constraint is removed using the 'crm_resource -U' command or manually with cibadmin\n",\
					"\tThis will be the case even if", "is the last node in the cluster", "Must supply a resource id with -r\n", \
					"not moved:", "active on multiple nodes\n", "Please input again", \
					"is not a known node\n", "is already active on", "not-active and no preferred location specified.\n", \
					"You need to specify a resource type with -t", "Unknown command:", "Try using -f\n", \
					"Migration will take effect until:", "Migration will take effect at:"
					]
			m = re.search("WARNING: Creating rsc_location constraint (.+) with a score of -INFINITY for resource (.*) on (.*)",msg)
			if m != None:
				msg = msg.replace(m.group(), _("WARNING: Creating rsc_location constraint '%s' with a score of -INFINITY for resource %s on %s.") \
					%(m.groups()[0], m.groups()[1], m.groups()[2]))
	
			for replace in replace_msgs :
				msg = msg.replace(replace, _(replace))
			msgbox(top_window, msg)


        def on_unmigrate_rsc(self, action) :
                rsc_locations = {}
                for rsc_location in manager.xml_nodes["cib"].getElementsByTagName("rsc_location") :
                        id = str(rsc_location.getAttribute("id"))
                        rsc_locations[id] = rsc_location
                migrate_ids = {}
                rsc_ids = []
                for id in rsc_locations :
			for prefix in ["cli-prefer-", "cli-standby-", "cli-ban-"] :
                                if id.startswith(prefix) :
                                        rsc_id = str(rsc_locations[id].getAttribute("rsc"))
                                        if not migrate_ids.has_key(rsc_id) :
                                                migrate_ids[rsc_id] = []
                                        migrate_ids[rsc_id].append(id)

                all_str = _("all migrated resources")
                rsc_list = migrate_ids.keys()[:]
                rsc_list.insert(0, all_str)

                (cur_type, cur_name) = self.manage_tree.get_selected_node()
                if cur_name in migrate_ids :
                        default_option = cur_name
                else :
                        default_option = all_str
                unmigrate = kvbox(_("Clear Migrate Constraints"), None,
                                [Field("rsc", _("Resource"), default_option, rsc_list, False, entry_editable = False)])

                if unmigrate != None :
                        if unmigrate["rsc"] == all_str :
                                for rsc_id in migrate_ids.keys() :
                                        for id in migrate_ids[rsc_id] :
                                                xml_str = rsc_locations[id].toxml().replace("\n", "")
                                                manager.cib_do_cmd("cib_delete\nconstraints\n%s"%(str(xml_str)))
                        else :
                                for id in migrate_ids[unmigrate["rsc"]] :
                                        xml_str = rsc_locations[id].toxml().replace("\n", "")
                                        manager.cib_do_cmd("cib_delete\nconstraints\n%s"%(str(xml_str)))

        def on_manage_rsc(self, action) :
                (cur_type, cur_name) = self.manage_tree.get_selected_node()

                if action.get_name() == "managersc" :
                        is_managed = "true"
                elif action.get_name() == "unmanagersc" :
                        is_managed = "false"
                else :
                        is_managed = "#default"

                if validate_type == "dtd" :
                        metaattr_name = "is_managed"
                else :
                        metaattr_name = "is-managed"

                if is_managed == "#default" :
                        manager.do_cmd("del_rsc_attr\n%s\nmeta\n%s"%(manager.obj_real_id(cur_name), metaattr_name))
                else :
                        manager.do_cmd("set_rsc_attr\n%s\nmeta\n%s\n%s"%(manager.obj_real_id(cur_name), metaattr_name, is_managed))
                        if manager.failed_reason != "" :
                                msgbox(top_window, manager.failed_reason)

        def on_crm_rsc_cmd(self, action) :
                global top_window
                cmd = action.get_name()
                node_list = manager.get_normal_nodes()
                if node_list == None :
                        node_list = []
                #node_options = node_list[:]
                #node_options.insert(0, "")

                title = _("%s Resources")%_(name_cap(cmd))
                dialog = gtk.Dialog(title, top_window, gtk.DIALOG_MODAL,
                        (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK))
                dialog.set_border_width(5)
                dialog.set_default_response(gtk.RESPONSE_OK)

                combos ={}
                for key in ["node"] :
                        hbox = gtk.HBox()
                        name_label = gtk.Label(_(name_cap(key)) + _(":"))
                        name_label.set_alignment(0, 0.5)

                        checkbutton = gtk.CheckButton()
                        checkbutton.add(name_label)
                        hbox.pack_start(checkbutton, False, padding=2)

                        value_widget = gtk.combo_box_new_text()
                        for node in node_list :
                                value_widget.append_text(node)
                        value_widget.set_sensitive(False)
                        hbox.pack_start(value_widget, True, padding=2)
                        combos[key] = value_widget

                        checkbutton.connect("toggled", self.on_checkbutton_toggled, value_widget)
                        dialog.vbox.pack_start(hbox, False, padding=2)
                widgets = {}
                widgets["combos"] = combos
                widget_group = WidgetGroup(widgets)

                dialog.show_all()

                save_top_window = top_window
                top_window = dialog

                ret = dialog.run()
                if ret in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT] :
                        top_window = save_top_window
                        dialog.destroy()
                        return

                cmd_args = widget_group.get_values()
                top_window = save_top_window
                dialog.destroy()

                #cmd_args = kvbox(_("%s Resources")%_(name_cap(cmd)), None,
                #               [Field("node", _("Node"), "", node_options, True, entry_editable = False)])

                #if cmd_args == None :
                #       return

                manager.do_cmd("crm_rsc_cmd\n\n%s\n%s"%(cmd, cmd_args.get("node", "")))
                if manager.failed_reason != "" :
			if re.match('^Waiting for.*replies from the CRMd.*$', manager.failed_reason) != None:
				return
                        msgbox(top_window, manager.failed_reason)

        def on_standby(self, action) :
                #(cur_type, cur_name) = self.manage_tree.get_selected_node()
                if confirmbox(top_window, _("Make") +" " +self.cur_node_name + " " +_("standby")+"?") == gtk.RESPONSE_YES:
                        #manager.do_cmd("standby\n"+cur_name + "\n" + "on")
			manager.do_cmd("crm_attribute\nnodes\nset\nstandby\ntrue\n%s\n\n"%self.cur_node_name)
                        if manager.failed_reason != "" :
                                msgbox(top_window, manager.failed_reason)

        def on_active(self, action) :
                #(cur_type, cur_name) = self.manage_tree.get_selected_node()
                if confirmbox(top_window, _("Make") +" " +self.cur_node_name + " " + _("active")+"?") == gtk.RESPONSE_YES :
                        #manager.do_cmd("standby\n"+cur_name + "\n" + "off")
			manager.do_cmd("crm_attribute\nnodes\nset\nstandby\nfalse\n%s\n\n"%self.cur_node_name)
                        if manager.failed_reason != "" :
                                msgbox(top_window, manager.failed_reason)

	def on_del_node(self, action):
		if self.cur_node_name in manager.get_dc():
			msgbox(top_window, _("Please do not delete the DC node!"))
			return

		ret = confirmbox(top_window, _("This will delete the %s \"%s\"")%(_("node"), self.cur_node_name),
				(gtk.STOCK_NO, gtk.RESPONSE_NO, gtk.STOCK_YES, gtk.RESPONSE_YES),
				_("Delete the selected object?"))
		if ret == gtk.RESPONSE_YES :
			del_node_id = None
			cmd = "crm_node -l"
			ret = manager.do_cmd("system\n%s"%(str(cmd)))
			if manager.failed_reason != "":
				msgbox(top_window, manager.failed_reason)
			try:
				for r in ret :
					if r.split()[1] == self.cur_node_name:
						del_node_id = r.split()[0]
						break
			except:
				pass

			if del_node_id != None:
				cmd = "crm_node --force -R %s"%(str(del_node_id))
				manager.do_cmd("system\n%s"%(str(cmd)))
				if manager.failed_reason != "":
					msgbox(top_window, manager.failed_reason)

			manager.del_node_constraints(self.cur_node_name)
			selected_node = None
			nodes = manager.xml_nodes["cib"].getElementsByTagName("node")
			for node in nodes:
				if node.getAttribute("uname") == self.cur_node_name:
					selected_node = node
					break
			if selected_node == None:
				return

			selected_node.parentNode.removeChild(selected_node)
			xml_str = selected_node.toxml().replace("\n", "")
			manager.cib_do_cmd("cib_delete\n%s\n%s"%(str("node"), str(xml_str)))
			if manager.failed_reason != "" :
				msgbox(top_window, manager.failed_reason)

	#neoshineha end ming.liu

class Manager :
	'''
	Manager will connect to mgmtd and control the main window
	'''
	connected = False
	window = None
	server = None
	username = None
	password = None
	cache = {}
	no_update_cache = {}
	parent = {}
	io_tag = None
	update_timer = -1
	active_nodes = []
	all_nodes = []
	try_nodes = []
	failed_reason = ""
	dtd_elems = {}
	session_lock = thread.allocate_lock()
	async_ret_lock = thread.allocate_lock()
	#async_ret_str = {}
	async_ret_list = {} 
	xml_nodes = {}
	active_cib = None
	validate_name = None
	profile = {}
	record_pending_newly_enabled = False

	#neoshineha ming.liu add

	def diskhb_labelbond(self, disklist, label):
		for device in disklist:
			cmd= "read -n16 line <" + " "+ device + " " + "&&" + " " + "echo $line"
			ret_label = window.do_cmd_with_pbar("system\n%s"%(cmd), _("Locate Device hb Used"), _("Locate the device hb used may take a while..."), _("Failed to locate!"),False)
			if ret_label == None:
				continue
			if ret_label[0] == label:
				return device

		return False

	def check_device(self, disk):
		m = re.match('^[a-zA-Z0-9._/-]+$', disk)
                if m is None:
                        return False

		if not disk.startswith("/dev/") or len(disk)<6:
			return False
		return True

	def get_quorum_policy(self):
		have_quorum = False
	        for attr_name in ["have-quorum", "have_quorum"] :
			try:
				attr_value = manager.xml_nodes["cib"].getAttribute(attr_name)
			except:
				return False
                	if attr_value != "" :
                        	if attr_value in ["true", "yes", "1"] :
                                	have_quorum = True
	                        break
		if not have_quorum:
			cluster_property_sets = manager.xml_nodes["cib"].getElementsByTagName("cluster_property_set")
	                if len(cluster_property_sets) == 0 :
        	                return False
                	#elif len(cluster_property_sets) == 1 :
			else:
        	                for nvpair in cluster_property_sets[0].getElementsByTagName("nvpair") :
                	                if nvpair.getAttribute("name")=="no-quorum-policy" and nvpair.getAttribute("value")=="ignore":
						return True
	                        return False
		return True

	def update_database(self, cmd):
		ret = manager.do_cmd_twice("update_sqldata\n%s\n%s"%("",str(cmd)))
		if manager.failed_reason != "":
			msgbox(top_window, _("Please refresh and retry!\n") + manager.failed_reason)
			return False
		for node in manager.get_dc():
			if node in manager.get_local_node():
				continue
                	ip = manager.get_one_node_ip(node)
			if ip == None:
				msgbox(top_window, _("Can not get the ipaddress of dc!") + _("Or can not be connected!") + "\n" + _("Please make sure that the environment is configured correctly!"))
				return False
			remote_cmd = "sqlite3 /usr/lib/ocf/lib/heartbeat/db/%s.db \"%s\""%(node,cmd)
			ret = manager.do_cmd_twice("ssh_node\n%s\n%s\n%s\n%s"%(str(ip), str("HASql"), str("qwert12345"), str(remote_cmd)))
			if manager.failed_reason != "":
				msgbox(top_window, _("Please refresh and retry!\n") + manager.failed_reason)
				return False

		return True

        def get_node_ip(self):
                #get_ip
                cmd = "crm_node -l"
                ret = manager.query("system\n%s"%(str(cmd)))
                node_ip = {}
                for r in ret:
			m = re.match("^(\w*)\s(.*)\smember", r)
                        if m is not None:
				node_id = m.groups()[0]
				node = m.groups()[1]
				node_ip[node] = []
				cmd = "corosync-cfgtool -a "+ node_id
                                ips = manager.query("system\n%s"%(str(cmd)))[0].split()
				for ip in ips:
					if ip!="127.0.0.1":
						node_ip[node].append(ip)
			if len(node_ip[node]) < 1 :
				m = re.match("^\w*\s(.*)\smember\s(.*)", r)
	                        if m is not None:
					node = m.groups()[0]
                	                node_ip[node] = []
					ips = m.groups()[1].split()
					i=0
					while i<len(ips)/2:
						m1=re.match("ip\((.*)\)",ips[i*2+1])
						if m1 is not None and m1.groups()[0]!="127.0.0.1":
							node_ip[node].append(m1.groups()[0])
						i=i+1

		return node_ip

	def get_one_node_ip(self, node):
		try:
			ip_list = self.get_node_ip()[node]
		except:
			return None

		for ip in ip_list:
                        cmd = "ping -c 1 " + ip
                        if "100% packet loss" not in str(self.do_cmd("system\n%s"%(str(cmd)))):
				return ip
                return None

	def del_node_constraints(self, del_node_id):
		if del_node_id != None:
			cmd = "crm_node --force -R %s"%(str(del_node_id))
			manager.do_cmd("system\n%s"%(str(cmd)))
			if manager.failed_reason != "":
				msgbox(top_window, manager.failed_reason)

		location_ids = []
		for rsc in manager.get_top_rsc():
			constraints = manager.do_cmd("get_rsc_constraints\n%s"%(rsc))
			for cons in constraints :
	                        #m = re.match('^.*\'(.*)\':(.*)=(.*)$', cons)
				m = re.match('^\s\s:\sNode\s(.*)\s*\(score=(.*)\,\sid=(.*)\)', cons)
	                        if m is None :
	                                continue
	                        if m.groups()[1].strip() == del_node_id: #location
	                                location_ids.append(m.groups()[2].strip())

		rsc_location_rule = []
		xml_constraints = manager.xml_nodes["cib"].getElementsByTagName("constraints")[0]
		for rsc_location in manager.xml_nodes["cib"].getElementsByTagName("rsc_location") :
			id = str(rsc_location.getAttribute("id"))
	                if id in location_ids:
				xml_constraints.removeChild(rsc_location)
				#xml_str = rsc_location.toxml().replace("\n", "")
	                        #manager.cib_do_cmd("cib_delete\n%s\n%s"%("", str(xml_str)))
				#if manager.failed_reason != "" :
				#	msgbox(top_window, manager.failed_reason)
                        else:
                                for rule in rsc_location.getElementsByTagName("rule") :
                                        id = str(rule.getAttribute("id"))
                                        if id in location_ids:
                                        	rsc_location.removeChild(rule)

                                        if len(rsc_location.getElementsByTagName("rule")) == 0:
                                                xml_constraints.removeChild(rsc_location)

                xml_str = xml_constraints.toxml().replace("\n", "")
                manager.cib_do_cmd("cib_replace\n%s\n%s"%(str("constraints"), str(xml_str)))

                if manager.failed_reason != "" :
                        msgbox(top_window, manager.failed_reason)

        def get_constraint(self, type, id) :
                if type == "rsc_location" :
                        location_attr_names = ["id","rsc","score", "boolean_op"]
                        expr_attr_names = ["id","attribute","operation","value"]
                        attrs = manager.query("get_co\nrsc_location\n"+id)
                        if attrs == None :
                                return None
                        location = dict(zip(location_attr_names,attrs[:4]))
                        location["exprs"] = []
                        for i in range((len(attrs)-len(location_attr_names))/len(expr_attr_names)) :
                                expr = dict(zip(expr_attr_names,attrs[4+i*4:8+i*4]))
                                location["exprs"].append(expr)
                        return location
                elif type == "rsc_order" :
                        order_attr_names = ["id","first","type","then"]
                        attrs = manager.query("get_co\nrsc_order\n" + id)
                        if attrs == None :
                                return None
                        order = dict(zip(order_attr_names,attrs))
                        return order
                elif type == "rsc_colocation" :
                        colocation_attr_names = ["id","with-rsc","rsc","score"]
                        attrs = manager.query("get_co\nrsc_colocation\n" + id)
                        if attrs == None :
                                return None
                        colocation = dict(zip(colocation_attr_names,attrs))
                        return colocation

	def get_status_node_links(self):
		try:
                	for status in self.query("status_hblinks"):
				if "FAULTY" in status:
					return False
		except:
			return True
		return True

	#neoshineha ming.liu end

		
	# cache functions
	def __init__(self) :
		self.load_profile()

	def cache_lookup(self, key) :
		if self.cache.has_key(key) :
			return self.cache[key]
		if self.no_update_cache.has_key(key) :
			return self.no_update_cache[key]
		return None
			
	def cache_update(self, key, data, keep_in_cache = False) :
		if not keep_in_cache :
			self.cache[key] = data
		else :
			self.no_update_cache[key] = data
			
	def cache_delkey(self, key) :
		if self.cache.has_key(key) : 
			del self.cache[key]
			
	def cache_clear(self) :
		self.cache.clear()
		
	# internal functions	
	def split_attr_list(self, attrs, keys) :
		attr_list = []
		if attrs != None :
			for i in range(0, len(attrs), len(keys)) :
				attr = {}
				for j in range (0, len(keys)) :
					attr[keys[j]] = attrs[i+j]
				attr_list.append(attr)
		return attr_list
		
	def run(self) :
		gtk.gdk.threads_init()
		gtk.main()
		if self.connected :
			mgmt_disconnect()
	
	# connection functions
	def load_profile(self) :
		keys = ["server", "user", "width", "height"]

		self.profile["server"] = "127.0.0.1"
		self.profile["user"] = "hacluster"
		self.profile["width"] = 790
		self.profile["height"] = 550

		save_path = os.environ["HOME"]+"/.haclient"
		if not os.path.exists(save_path) :
			return 
		try:
			values = pickle.load(file(save_path,"r"))
                        user_profile = dict(zip(keys, values))
                        self.profile.update(user_profile)
			return
		except:
			return

	def save_profile(self) :
		global top_window

                server = self.profile["server"]
                user = self.profile["user"]

                (width, height) = top_window.get_size()
                self.profile["width"] = width
                self.profile["height"] = height

		save_path = os.environ["HOME"]+"/.haclient"
		try:
			pickle.dump((server, user, width, height), file(save_path,"w"))
		except:
			os.remove(save_path)
		return
		
	def login(self, server, username, password) :
		# connect to one of the cluster
		self.failed_reason = ""
		if string.find(server, ":") != -1 :
			server_host, port = string.split(server,":")
		else :
			server_host = server
			port = ""

		try :
			ip = socket.gethostbyname(server_host)
		except socket.error :
			self.failed_reason = _("Can't resolve address of server ")+server_host
			return False

		try :
			ret = mgmt_connect(ip, username, password, port)
		except :
			self.failed_reason = _("Can't connect to server ")+server
			mgmt_disconnect()
			return False

		if ret != 0 :
			if ret == -1 :
				self.failed_reason = _("Can't connect to server ")+server
			elif ret == -2 :
				self.failed_reason =\
			 	_("Failed in the authentication.\n User Name or Password may be wrong." \
				"\n or the user doesn't belong to haclient group")
			else :
				self.failed_reason = _("Can't login to server.\n The protocols may be mismatched.")
			mgmt_disconnect()
			return False

		if not self.check_ha_version():
			self.failed_reason = _("Can't login to server.\n The license has expired.")
			mgmt_disconnect()
			return False
			
		window.statusbar.pop(1)	
		window.statusbar.push(1,_("Connected to ")+username+"@"+server_host)
		self.connected = True
		if server != None and server not in self.try_nodes :
			self.try_nodes.insert(0, server)
		self.server = server_host
		self.username = username
		self.password = password

		window.statusbar.push(2,_("Updating data from server..."))
		self.update_timer = gobject.timeout_add(500, self.update)
		
		self.do_cmd("regevt\nevt:cib_changed")
		self.do_cmd("regevt\nevt:disconnected")

		fd = mgmt_inputfd()
		self.io_tag = gobject.io_add_watch(fd, gobject.IO_IN, self.on_event, None)

		gobject.timeout_add(5000, self.update_crm_metadata, priority=gobject.PRIORITY_DEFAULT_IDLE)

		return True
	
        def check_ha_version(self):
                version_msg = manager.query("lic_verid")
                # Initialization/Cannot get license info
                if manager.failed_reason != "" or version_msg == None or version_msg == [] :
                        return False
                elif "trial" in version_msg:
                        return self.check_ha_expired()
                else:
                        return True

	def check_ha_expired(self):
		# Initialization/Cannot get license info
		self.do_cmd("lic_expire")
		if self.failed_reason == "":
			return True
		else:
			return False

	def query(self, query, keep_in_catch = False) :
		result = self.cache_lookup(query)
		if  result != None :
			return 	result
		result = self.do_cmd(query)
		self.cache_update(query, result, keep_in_catch)
		return result
		
	def do_cmd_twice(self, command):
		ret = self.do_cmd(command)
		if self.failed_reason != "" or ret == None :
			time.sleep(0.3)
			ret = self.do_cmd(command)
		return ret

	def do_cmd(self, command) :
		self.failed_reason = ""
		self.session_lock.acquire()
		ret_str = mgmt_sendmsg(command)
		self.session_lock.release()
		if ret_str == None :
			debug(str(string.split(command, "\n"))+":None")
			self.failed_reason = "return None"
			return None
 		while len(ret_str)>=4 and ret_str[:4] == "evt:" :
			gobject.idle_add(self.on_event, None, None, ret_str)
			self.session_lock.acquire()
 			ret_str = mgmt_recvmsg()
			self.session_lock.release()
			if ret_str == None :
				debug(str(string.split(command, "\n"))+":None")
				self.failed_reason = "return None"
				return None

		return self.ret_str2list(ret_str, command)

	def ret_str2list(self, ret_str, command) :
		self.failed_reason = ""
		ret_list = string.split(ret_str, "\n")
		if ret_list[0] != "o" :
			debug(str(string.split(command, "\n"))+":"+ str(ret_list))
			if len(ret_list) > 1 :
				self.failed_reason = string.join(ret_list[1:],"\n")
			return None
		debug(str(string.split(command, "\n"))+":"+ str(ret_list))
		return ret_list[1:]

	def process_ret(self, command, ret_str) :
		self.failed_reason = ""
		if ret_str == None :
			debug(str(string.split(command, "\n"))+":None")
			self.failed_reason == "return None"
			return None

		return self.ret_str2list(ret_str, command)

	def async_sendmsg(self, command) :
		self.session_lock.acquire()
		gobject.source_remove(self.io_tag)
		async_ret_str = mgmt_thread_sendmsg(command)
		fd = mgmt_inputfd()
		self.io_tag = gobject.io_add_watch(fd, gobject.IO_IN, self.on_event, None)
		self.session_lock.release()

		self.async_ret_lock.acquire()
		self.async_ret_list[command] = self.process_ret(command, async_ret_str)
		self.async_ret_lock.release()
		
	def async_do_cmd(self, command) :
		self.async_ret_lock.acquire()
		#self.async_ret_str = {}
		#self.async_ret_list = {}
		if self.async_ret_list.has_key(command) :
			self.async_ret_list.pop(command)
		self.async_ret_lock.release()
		thread.start_new(self.async_sendmsg, (command, ))
		
	def logout(self) :
		mgmt_disconnect()
		gobject.source_remove(self.io_tag)
		self.connected = False
		window.update()
		window.statusbar.pop(1)
		
	# event handler	
	def on_reconnect(self) :
		if self.all_nodes == [] :
			window.statusbar.pop(1)
			return False

		try_nodes = self.try_nodes[:]
		'''for node in self.all_nodes :
			if node not in try_nodes :
				try_nodes.append(node)'''

		for server in try_nodes :
			if self.login(server, self.username, self.password) :
				return False
		return True

	def process_event(self, event) :
		if event == "evt:cib_changed" :
			self.set_update()

		elif event == None or event == "evt:disconnected" :
			self.logout()

			try_nodes = self.try_nodes[:]
			'''for active_node in self.active_nodes :
				if active_node not in try_nodes :
					try_nodes.append(active_node)'''

			for server in try_nodes :
				if self.login(server, self.username, self.password) :
					break
			else :
				#neoshineha ming.liu add
	                        for child in window.mainview_sw.get_children():
        	                        window.mainview_sw.remove(child)
                	        for child in window.sub_vbox.get_children():
                        	        window.sub_vbox.remove(child)
                                	window.sub_vbox.hide_all()
                        	#neoshineha ming.liu add end

				window.statusbar.push(1,_("Reconnecting..."))
				gobject.timeout_add(1000, self.on_reconnect)

	def set_update(self) :
		if self.update_timer != -1 :
			gobject.source_remove(self.update_timer)
		else :
			window.statusbar.push(2,_("Updating data from server..."))
		self.update_timer = gobject.timeout_add(500, self.update)
	
	def on_event(self, source, condition, event_str) :
		if event_str == None : 	# called by gtk
			self.session_lock.acquire()
			event = mgmt_recvmsg()
			self.session_lock.release()
			debug("on_event:"+str(event))
			self.process_event(event)
			return True
		else :					# called by do_cmd
			event = event_str 
			log("on_event: from message queue: "+str(event))
			self.process_event(event)
			return False

	def cib_do_cmd(self, command):
		self.failed_reason = ""
		ret_str = mgmt_sendmsg(command)
		if ret_str == None:
			debug(command + ":None")
			self.failed_reason = "return None"
			return None
		ret_list = string.split(ret_str, "\n")
		if ret_list[0] != "o":
			debug(str(string.split(command, "\n"))+":"+str(ret_list))
			if len(ret_list) > 1:
				self.failed_reason = string.join(ret_list[1:], "\n")
			return None
		return string.join(ret_list[1:], "\n")

	def update_cib_xml(self) :
		global validate_type
		xml_nodes = self.xml_nodes
		cib_xml = self.cib_do_cmd("cib_query\ncib")
		if self.failed_reason != "" :
			#msgbox(top_window, self.failed_reason)
			log(self.failed_reason)
			return False 

		if cib_xml == None or cib_xml == "" :
			#msgbox(top_window, _("Cannot get the CIB"))
			log("Cannot get the CIB")
			return False

		try :
			xml_nodes["cib"] = parseString(cib_xml).documentElement
		except xml.parsers.expat.ExpatError, msg :
			#msgbox(top_window, _("Failed to parse the CIB") + _(": ") + str(msg))
			log("Failed to parse the CIB: " + str(msg))
			return False 
			
		"""xml_status = self.cib_do_cmd("cib_query\nstatus")
		xml_rscs = self.cib_do_cmd("cib_query\nresources")
		xml_nodes = self.cib_do_cmd("cib_query\nnodes")
		xml_constraints = self.cib_do_cmd("cib_query\nconstraints")
		xml_crm_config = self.cib_do_cmd("cib_query\ncrm_config")"""

		if xml_nodes.get("cib") == None :
			#msgbox(top_window, _("Cannot parse the CIB"))
			log("Cannot parse the CIB")
			return False

		validate_type = self.get_validate_type()
		saved_validate_name = self.validate_name
		self.validate_name = self.get_validate_name()

		if validate_type == "dtd" :
                        if not support_pyxml :
                                log("Pacemaker GUI requires pyxml package to process DTD")
                                msgbox(top_window, _("Pacemaker GUI requires pyxml package to process DTD"))
                                sys.exit()

			dtd_elem = self.get_dtd_elem("cib")
			for (name, mod) in dtd_elem.get_content_model()[1] :
				if mod != '' :
					continue
				
				xml_nodes[name] = xml_nodes["cib"].getElementsByTagName(name)[0]
				if xml_nodes.get(name) == None :
					continue
				sub_dtd_elem = manager.get_dtd_elem(name)
				for (sub_name, sub_mod) in sub_dtd_elem.get_content_model()[1] :
					if sub_mod != '' :
						continue
					xml_nodes[sub_name] = xml_nodes[name].getElementsByTagName(sub_name)[0]
		else :
			if self.validate_name != saved_validate_name :
				self.rng_docs = {}
				self.rng_str_docs = {}
				self.update_rng_docs(self.validate_name, self.validate_name+".rng")
				self.supported_rsc_types = self.get_supported_rsc_types()

		return True

		"""config_xml = self.cib_xml.getElementsByTagName("configuration")
		self.crm_xml = config_xml.getElementsByTagName("crm_config")
		self.nodes_xml = config_xml.getElementsByTagName("nodes")
		self.rscs_xml = config_xml.getElementsByTagName("resources")
		self.cns_xml = config_xml.getElementsByTagName("constraints")
		self.status_xml =  self.cib_xml.getElementsByTagName("status")
	
		try:
			self.cib_xml = parseString(xml_cib).documentElement
			self.status_xml = parseString(xml_status)
			self.rscs_xml = parseString(xml_rscs)
			self.nodes_xml = parseString(xml_nodes)
			self.cns_xml = parseString(xml_constraints)
			self.crm_xml = parseString(xml_crm_config)
		except xml.parsers.expat.ExpatError:
			self.status_xml = None
			self.rscs_xml = None
			self.nodes_xml = None
			self.crm_xml = None
			self.cns_xml = None
			debug("fail to parse xml info")
			return None"""

	def get_active_cib(self) :
		active_cib = manager.do_cmd("active_cib")
		if active_cib == None or len(active_cib) == 0 :
			return

		if len(active_cib[0]) > 0 :
			self.active_cib = active_cib[0]
		else :
			self.active_cib = ""

	def get_supported_rsc_types(self) :
		rsc_types = []
		if validate_type == "dtd" :
			dtd_elem = manager.get_dtd_elem("resources")
			for (name, mod) in dtd_elem.get_content_model()[1] :
				rsc_types.append(name)
		else :
			sorted_rng_nodes = manager.sorted_sub_rng_nodes_by_name("resources")
			for rng_node in sorted_rng_nodes.get("element", []) :
				rsc_types.append(rng_node[0][1].getAttribute("name"))

		return rsc_types

	def find_xml_node(self, obj_type, obj_name) :
		for xml_node in self.xml_nodes["cib"].getElementsByTagName(obj_type) :
			if xml_node.getAttribute("id") == obj_name :
				return xml_node
		return None

	def find_attribute(self, obj_type, attribute_name) :
		for xml_node in self.xml_nodes["cib"].getElementsByTagName(obj_type) :
			for nv_xml_node in xml_node.getElementsByTagName("nvpair") :
				if nv_xml_node.getAttribute("name") == attribute_name :
					return nv_xml_node.getAttribute("value")
		return None

	def set_crm_attribute(self, type, name, value) :
                for xml_node in self.xml_nodes["cib"].getElementsByTagName(type) :
                        for attr_node in xml_node.getElementsByTagName("nvpair") :
                                if attr_node.getAttribute("name") == name :
                                        attr_id = str(attr_node.getAttribute("id"))
                                        self.do_cmd("crm_attribute\n%s\nset\n%s\n%s\n\n\n%s"
                                                        %(type, name, value, attr_id))
                                        return
 
                        for child_node in xml_node.childNodes :
                                if child_node.nodeType != xml.dom.Node.ELEMENT_NODE :
                                        continue
                                set_id = str(child_node.getAttribute("id"))
                                self.do_cmd("crm_attribute\n%s\nset\n%s\n%s\n\n%s\n"
                                                %(type, name, value, set_id))
                                return
 
                self.do_cmd("crm_attribute\n%s\nset\n%s\n%s\n\n\n"%(type, name, value))

	def node_name(self, node_id) :
		for node_xml_node in manager.xml_nodes["cib"].getElementsByTagName("node") :
			if node_xml_node.getAttribute("id") == node_id :
				node_name = node_xml_node.getAttribute("uname")
				return node_name
		return ""

	def validate_cib(self, cib_xml_node = None) :
		if cib_xml_node == None :
			 cib_xml_node = manager.xml_nodes["cib"]

		if validate_type == "dtd" :
			is_valid = True
		elif not support_lxml :
			is_valid = True
		else :
			is_valid = self.validate_with_rng(cib_xml_node)

		return is_valid

	def validate_with_rng(self, cib_xml_node) :
		rng_doc = self.tmp_rng_doc()
		if rng_doc == None :
			msgbox(top_window, _("Cannot expand the Relax-NG schema"))
			return False
		
		try :
			cib_doc = etree.fromstring(cib_xml_node.toxml())
		except etree.Error, msg :
			msgbox(top_window, _("Failed to parse the CIB XML") + _(": ") + str(msg))
			return False
			
		try :
			relaxng = etree.RelaxNG(file = rng_doc)
		except etree.Error, msg :
			msgbox(top_window, _("Failed to parse the Relax-NG schema") + _(": ") + str(msg))
			return False
		#try :
		#	relaxng.assertValid(cib_doc)
		#except etree.DocumentInvalid, err_msg :
		#	print err_msg
		#	print relaxng.error_log
		try :
			etree.clear_error_log()
		except :
			try :
				etree.clearErrorLog()
			except :
				pass

		is_valid = relaxng.validate(cib_doc)
		if not is_valid :
			error_msg = ""
			for error_entry in relaxng.error_log :
				error_msg += error_entry.level_name + ": " + error_entry.message + "\n"
			msgbox(top_window, _(error_msg))

		delete_dir(os.path.dirname(rng_doc))

		return is_valid

	def tmp_rng_doc(self) :
		try :
			tmp_dir = tempfile.mkdtemp()
		except IOError, msg :
			msgbox(top_window, _("I/O error") + _(": ") + str(msg))
			return None
		for rng_doc_name in self.rng_str_docs :
			rng_doc_filename = os.path.join(tmp_dir, rng_doc_name)
			try :
				fd = os.open(rng_doc_filename, os.O_RDWR|os.O_CREAT|os.O_TRUNC, 0644)
			except OSError, msg :
				msgbox(top_window, _("System error") + _(": ") + str(msg))
				return None

			rng_doc_str = self.rng_str_docs[rng_doc_name]

			try :
				os.write(fd, rng_doc_str)
			except OSError, msg :
				msgbox(top_window, _("System error") + _(": ") + str(msg))
				os.close(fd)
				return None
			os.close(fd)

		if self.validate_name + ".rng" in  self.rng_str_docs :
			return os.path.join(tmp_dir, self.validate_name + ".rng")
		else :
			return None

	def update_rng_docs(self, validate_name = "", file= "") :
		self.rng_docs[file] = self.get_start_rng_node(validate_name, file)
		if self.rng_docs[file] == None :
			return
		for extern_ref in self.rng_docs[file][0].getElementsByTagName("externalRef") :
			href_value = extern_ref.getAttribute("href")
			if self.rng_docs.get(href_value) == None :
				self.update_rng_docs(validate_name, href_value)	

	def get_start_rng_node(self, validate_name = "", file = "") :
		schema_info = validate_name + " " + file
		crm_schema = self.get_crm_schema(validate_name, file)
		if crm_schema == None :
			#msgbox(top_window, _("Cannot get the Relax-NG schema") + _(": ") + schema_info)
			log("Cannot get the Relax-NG schema: " + schema_info)
			return None

		self.rng_str_docs[file] = crm_schema

		try :
			rng_doc = parseString(crm_schema).documentElement
		except xml.parsers.expat.ExpatError, msg :
			#msgbox(top_window, _("Failed to parse the Relax-NG schema") + _(": ") + str(msg) + schema_info)
			log("Failed to parse the Relax-NG schema: " + str(msg) + schema_info)
			return None

		start_nodes = rng_doc.getElementsByTagName("start")
		if len(start_nodes) > 0 :
			start_node = start_nodes[0] 
			return (rng_doc, start_node)
		else :
			#msgbox(top_window, _("Cannot get started in Relax-NG schema") +_(": ") + schema_info)
			log("Cannot get started in Relax-NG schema: " + schema_info)
			return None

		#sub_start_node = None
		#for sub_start_node in start_node.childNodes :
		#	if sub_start_node.nodeType == xml.dom.Node.ELEMENT_NODE :
		#		break
			
		##sub_start_nodes = self.get_sub_rng_nodes(start_node)["req_elem_nodes"]
		##if sub_start_nodes == [] :
		#if sub_start_node == None :
		#	#msgbox(top_window, _("Cannot get the start element in Relax-NG schema: ") + schema_info)
		#	log("Cannot get the start element in Relax-NG schema: " + schema_info)
		#	return None
		#else :
		#	return (rng_doc, sub_start_node)

	def get_rng_elem(self, elem_name) :
		elem_node = None
		for (rng_doc, start_node) in self.rng_docs.values() :
			for elem_node in rng_doc.getElementsByTagName("element") :
				if elem_node.getAttribute("name") == elem_name :
					return (rng_doc, elem_node)
		return None

	def get_sub_rng_nodes(self, rng_doc, rng_node) :
		sub_rng_nodes = []
		#sub_rng_nodes = {}
		#req_elem_nodes = []
		#attr_nodes = []
		for child_node in rng_node.childNodes :
			if child_node.nodeType != xml.dom.Node.ELEMENT_NODE :
				continue
			if child_node.tagName == "ref" :
				for def_node in rng_doc.getElementsByTagName("define") :
					if def_node.getAttribute("name") == child_node.getAttribute("name") :
						break
				sub_rng_nodes.extend(self.get_sub_rng_nodes(rng_doc, def_node))
			elif child_node.tagName == "externalRef" :
				nodes = self.get_sub_rng_nodes(*self.rng_docs[child_node.getAttribute("href")])
				sub_rng_nodes.extend(nodes)
			elif child_node.tagName in ["element", "attribute", "value", "data", "text"] :
				sub_rng_nodes.append([(rng_doc, child_node)])
			elif child_node.tagName in ["interleave", "optional", "zeroOrMore", "choice", "group", "oneOrMore"] :
				nodes = self.get_sub_rng_nodes(rng_doc, child_node)
				for node in nodes :
					node.append(child_node)
				sub_rng_nodes.extend(nodes)
		#sub_rng_nodes["req_elem_nodes"] = req_elem_nodes
		return sub_rng_nodes

	def sorted_sub_rng_nodes_by_name(self, obj_type) :
		rng_node = self.get_rng_elem(obj_type)	
		if rng_node == None or rng_node[1] == None :
			# msgbox(top_window, _("Cannot get %s in Relax-NG schema")%obj_type)
			return None
		return self.sorted_sub_rng_nodes_by_node(*rng_node)

	def sorted_sub_rng_nodes_by_node(self, rng_doc, rng_node) :
		sub_rng_nodes = manager.get_sub_rng_nodes(rng_doc, rng_node)
		sorted_nodes = {}
		for sub_rng_node in sub_rng_nodes :
			name = sub_rng_node[0][1].tagName
			if sorted_nodes.get(name) == None :
				sorted_nodes[name] = []
			sorted_nodes[name].append(sub_rng_node)
		return sorted_nodes

	def find_decl(self, rng_node, name, first = True) :
		decl_node_index = 0
		for decl_node in rng_node[1:] :
			if decl_node.tagName == name :
				decl_node_index = rng_node.index(decl_node) - len(rng_node)
				if first :
					break
		return decl_node_index

	def get_decl_rng_nodes(self, rng_node) :
		decl_rng_nodes = {}
		choice_index = manager.find_decl(rng_node, "choice", False)
		if choice_index != 0 :
			decl_rng_nodes["choice"] = rng_node[choice_index]

		first_choice_index = manager.find_decl(rng_node, "choice")
		if first_choice_index != choice_index :
			decl_rng_nodes["first_choice"] = rng_node[first_choice_index]

		group_index = manager.find_decl(rng_node, "group", False)
		if group_index != 0 :
			decl_rng_nodes["group"] = rng_node[group_index]

		first_group_index = manager.find_decl(rng_node, "group")
		if first_group_index != group_index :
			decl_rng_nodes["first_group"] = rng_node[first_group_index]

		return decl_rng_nodes

	def get_sorted_decl_nodes(self, decl_nodes_list, decl_type) :
		sorted_nodes = []
		for rng_nodes in decl_nodes_list :
			rng_node = rng_nodes.get(decl_type)
			if rng_node != None and rng_node not in sorted_nodes :
				sorted_nodes.append(rng_node)
		return sorted_nodes

	def get_rng_attr_type(self, attr_rng_node) :
		sub_rng_nodes = self.sorted_sub_rng_nodes_by_node(*attr_rng_node[0])
		for sub_rng_node in sub_rng_nodes.get("data", []) :
			return sub_rng_nodes["data"][0][0][1].getAttribute("type")

		return None

	def real_add_obj_type(self, xml_node, obj_type_name, is_wizard = False) :
		sub_attr_is_any_name = False 
		if validate_type == "dtd" :
			dtd_elem = manager.get_dtd_elem(obj_type_name)
			sub_attr_list = dtd_elem.get_attr_list()
		else :
			sorted_rng_nodes = manager.sorted_sub_rng_nodes_by_name(obj_type_name)
			sub_attr_list = []
			sub_elem_type_list = []
			sub_elem_is_any_name = False
			if sorted_rng_nodes != None :
				sub_attr_rng_nodes = sorted_rng_nodes.get("attribute", [])
				sub_elem_rng_nodes = sorted_rng_nodes.get("element", [])
				for rng_node in sub_attr_rng_nodes :
					name = rng_node[0][1].getAttribute("name")
					if name == "" :
						sub_attr_is_any_name = True
					elif sub_attr_list.count(name) == 0 :
						sub_attr_list.append(name)
				for rng_node in sub_elem_rng_nodes :
					name = rng_node[0][1].getAttribute("name")
					if name == "" :
						sub_elem_is_any_name = True
					elif sub_elem_type_list.count(name) == 0 :
						sub_elem_type_list.append(name)
			else :
				sub_attr_is_any_name = True
				sub_elem_is_any_name = True
				sub_elem_rng_nodes = []
					
		if not sub_attr_is_any_name and (len(sub_attr_list) == 0 \
				or ((mode_level != 2 or is_wizard) and obj_type_name in
				["meta_attributes", "instance_attributes", "operations",
				"cluster_property_set", "utilization"])) :
			new_mid_elem = None
			impl = getDOMImplementation()
			elem_node_list = []
			for elem_node in xml_node.getElementsByTagName(obj_type_name) :
				if elem_node in xml_node.childNodes :
					elem_node_list.append(elem_node)
			if len(elem_node_list) == 0 :
				newdoc = impl.createDocument(None, obj_type_name, None)
				mid_elem = newdoc.documentElement
				xml_node.appendChild(mid_elem)
				new_mid_elem = mid_elem

				if sub_attr_list.count("id") > 0 :
					mid_id = manager.auto_unique_id(mid_elem, obj_type_name)
					mid_elem.setAttribute("id", mid_id)
			else :
				mid_elem = elem_node_list[0]

			if validate_type == "dtd" :
				(sep,cont,mod) = dtd_elem.get_content_model()
				if len(cont) > 0 :
					if len(sub_attr_list) == 0 :
						sub_obj_type = cont[0][0]
					else :
						sub_obj_type = cont[1][0]
						sub_elem_node_list = []
						for sub_elem_node in mid_elem.getElementsByTagName(sub_obj_type) :
							if sub_elem_node in mid_elem.childNodes :
								sub_elem_node_list.append(sub_elem_node)
						if len(sub_elem_node_list) == 0 :
							newdoc = impl.createDocument(None, sub_obj_type, None)
							sub_mid_elem = newdoc.documentElement
							mid_elem.appendChild(sub_mid_elem)
							mid_elem = sub_mid_elem
							if new_mid_elem == None :
								new_mid_elem = mid_elem
						else :
							mid_elem = sub_elem_node_list[0]
							
						sub_dtd_elem = manager.get_dtd_elem(sub_obj_type)
						(sub_obj_type, mod) = sub_dtd_elem.get_content_model()[1][0]
				else :
					return (None, None, None)
			else:
				sub_obj_type = None
				for sub_elem_rng_node in sub_elem_rng_nodes :
					if manager.find_decl(sub_elem_rng_node, "optional") != 0  :
						continue
					sub_obj_type = sub_elem_rng_node[0][1].getAttribute("name")
					break

				if sub_obj_type == None :
					return (None, None, None)

			return (mid_elem, sub_obj_type, new_mid_elem)
		else :
			return (xml_node, obj_type_name, None)

	def get_obj_ids(self, xml_node) :
		id_list = []
		node_id = xml_node.getAttribute("id")
		if node_id != "" and id_list.count(node_id) == 0 :
			id_list.append(node_id)
		for child_node in xml_node.childNodes :
			if child_node.nodeType != xml.dom.Node.ELEMENT_NODE :
				continue
			id_list.extend(self.get_obj_ids(child_node))
		return id_list

	def exist_ids(self, xml_node = None) :
		all_ids = manager.get_obj_ids(manager.xml_nodes["cib"])

		top_types = ["crm_config","rsc_defaults", "op_defaults", "nodes", "resources", "constraints", "acls", "fencing-topology", "status"]

		if xml_node == None :
			return all_ids

		top_parent = xml_node
		while top_parent.parentNode.tagName not in top_types :
			top_parent = top_parent.parentNode

		other_ids = manager.get_obj_ids(top_parent)

		for id in other_ids :
			if id not in all_ids :
				all_ids.append(id)

		current_id = xml_node.getAttribute("id")
		if current_id in all_ids :
			all_ids.remove(current_id)

		return all_ids

	def auto_id_prefix(self, xml_node, name) :
		parent_node = xml_node.parentNode
		parent_type = parent_node.tagName
		parent_id = parent_node.getAttribute("id")

		if parent_type == "crm_config" :
			return "cib-bootstrap-options"
		elif parent_type in ["rsc_defaults", "op_defaults"] :
			return parent_type + "-options"
		elif parent_type == "node" :
			if xml_node.tagName != "instance_attributes" :
                                return "nodes-" + parent_id + "-" + xml_node.tagName
                        else :
                                return "nodes-" + parent_id
		elif name == "fencing-level" :
                        return name

		if parent_id == "" :
			parent_parent_node = xml_node.parentNode.parentNode
			parent_parent_id = parent_parent_node.getAttribute("id")
			if parent_parent_id == "" :
				parent_parent_type = parent_parent_node.tagName
				id_prefix = parent_parent_type + "-" + parent_type + "-" + name
			else :
				id_prefix = parent_parent_id + "-" + parent_type + "-" + name
		else :
			id_prefix = parent_id + "-" + name

		return id_prefix

	def get_unique_id(self, id_prefix, xml_node = None) :
		all_exist_ids = self.exist_ids(xml_node)
		valid_id_prefix = self.sanify_id(id_prefix)

		id_suffix = ""
		new_id = valid_id_prefix 
		while new_id in all_exist_ids :
			if id_suffix == "" :
				id_suffix = 0
			else :
				id_suffix += 1

			new_id = valid_id_prefix + "-" + str(id_suffix)

		return new_id

	def sanify_id(self, id) :
		valid_prefix = "_"
		valid_chrs = "-_."
		for i in range(len(id)) :
			if id[i].isalpha() or id[i] in valid_prefix :
				break

		valid_id = ""
		for chr in id[i:] :
			if chr.isalnum() or chr in valid_chrs :
				valid_id += chr
			else :
				valid_id += '.'
		return valid_id

	def auto_unique_id(self, xml_node, name) :
		id_prefix = self.auto_id_prefix(xml_node, name)
		return self.get_unique_id(id_prefix, xml_node)

	def update(self) :
		self.cache_clear()
		if not manager.connected :
			retval = False
		elif self.update_cib_xml() :
			self.get_active_cib()
			self.parent = {}
			window.update()
			retval = False
		else :
			retval = True
		gc.collect()
		self.update_timer = -1
		return retval

	def get_validate_type(self) : 
		validate_list = {
			"": "dtd",
			"pacemaker-0.6": "dtd",
			"transitional-0.6": "dtd",
			"pacemaker-0.7": "rng",
			"pacemaker-1.0": "rng"
		}
		validate_name = self.get_validate_name()
		if validate_name == None :
			return None
		else :
			return validate_list.get(validate_name)

	def get_validate_name(self) :
		if self.xml_nodes.get("cib") != None :
			return self.xml_nodes["cib"].getAttribute("validate-with")
		else :
			return None

	def get_crm_schema(self, validate_name="", file="") :
		lines = self.query("crm_schema\n%s\n%s"%(str(validate_name), str(file)))
		if lines == None :
			return None
		schema = "\n".join(lines)
		return schema

	def get_crm_dtd(self):
		lines = self.query("crm_dtd", True)
		if lines == None:
			return None
		dtd = "\n".join(lines)

		return dtd
		
	def get_dtd_elem(self, elem_name) :
		if not self.dtd_elems.has_key(elem_name) :
			dtd = self.get_crm_schema(self.validate_name)
			if dtd == None :
				#msgbox(top_window, _("Cannot get the DTD") + _(": ") + self.validate_name)
				log("Cannot get the DTD:" + self.validate_name)
				return None
			complete_dtd = load_dtd_string(dtd)
			self.dtd_elems[elem_name] = complete_dtd.get_elem(elem_name)
		
		return self.dtd_elems[elem_name]

	# cluster functions		
	def update_crm_metadata(self) :
		for crm_cmd in ["pengine", "crmd"] :
			self.query("crm_metadata\n%s"%(crm_cmd),True)
		return False

	def get_crm_metadata(self, crm_cmd) :
		if crm_cmd == None :
			return None
		lines = self.query("crm_metadata\n%s"%(crm_cmd),True)

		if lines == None :
			return None
		meta_data = "\n".join(lines)

		try :
			doc_xml = parseString(meta_data).documentElement
		except xml.parsers.expat.ExpatError, msg :
			log("Failed to parse the metadata of %s: %s"%(crm_cmd, msg))
			return None
			
		meta = RAMeta()
		meta.name = doc_xml.getAttribute("name")

		meta.version = ""
		version_xml = doc_xml.getElementsByTagName("version")
		if version_xml != [] and version_xml[0] in doc_xml.childNodes :
			meta.version = version_xml[0].childNodes[0].data

		meta.longdesc = self.get_locale_desc(doc_xml, "longdesc");
		meta.shortdesc = self.get_locale_desc(doc_xml, "shortdesc");
		
		params = {}
		for param_xml in doc_xml.getElementsByTagName("parameter") :
			param = {}
			param["name"] = param_xml.getAttribute("name")
			param["unique"] = param_xml.getAttribute("unique")
			param["longdesc"] = self.get_locale_desc(param_xml, "longdesc");
			param["shortdesc"] = self.get_locale_desc(param_xml, "shortdesc");
			content_xml = param_xml.getElementsByTagName("content")[0]
			content = {}
			content["type"] = content_xml.getAttribute("type")
			content["default"] = content_xml.getAttribute("default")
			if content["type"] == "enum" :
				values_tag = "Allowed values:"
				index = param["longdesc"].rfind(values_tag)
				if index != -1:
					strings = param["longdesc"][index+len(values_tag):].split(",")
					content["values"] = []
					for string in strings:
						content["values"].append(string.strip())
				
			param["content"] = content

			params[param["name"]] = param

		param_names = params.keys()
		param_names.sort()

		meta.parameters = []
		for param_name in param_names :
			meta.parameters.append(params[param_name])

		return meta

	def get_cluster_type(self) :
		typelist = manager.query("cluster_type")
		if typelist != None and len(typelist) > 0 :
			cluster_type = typelist[0]
		else :
			cluster_type = ""

		return cluster_type

	def get_hb_config(self) :
		values = manager.query("hb_config")
		hb_config = {}
		if values != None:
			i = 0
			while i < len(values) :
				hb_config[values[i]] = values[i+1]
				i += 2
		return hb_config

	def get_cluster_config(self) :
		config = {}
		cluster_type = self.get_cluster_type()
		if cluster_type == "heartbeat" :
			config = self.get_hb_config()

		return config
				
	# node functions
	def get_dc(self):
		return self.query("dc")

	def get_local_node(self):
		return self.query("get_local_node")

	def get_all_nodes(self) :
		all_nodes = self.query("all_nodes")
		if all_nodes == None :
			all_nodes = self.query("crm_nodes")

		if all_nodes != None :
			self.all_nodes = all_nodes
		else :
			self.all_nodes = []

		return self.all_nodes

	def get_nodetype(self, node):
		node_type = self.query("node_type\n%s"%node)
		if node_type != None and len(node_type) > 0 :
			return node_type[0]
		else :
			return None
	
	def get_normal_nodes(self) :
		nodes = self.query("all_nodes")
		if nodes == None :
			return self.get_crm_nodes()

		normal_nodes = []
		for node in nodes :
			if self.get_nodetype(node) == "normal" :
				normal_nodes.append(node)
		return normal_nodes

	def get_active_nodes(self):
		active_nodes = self.query("active_nodes")
		if active_nodes != None :
			self.active_nodes = active_nodes
		else :
			self.active_nodes = []

		return self.active_nodes
	
	def get_crm_nodes(self):
		return self.query("crm_nodes")
				
	def get_node_config(self, node) :
		node_attr_names = ["uname", "online","standby", "unclean", "shutdown",
				   "expected_up","is_dc","type", "pending","standby_onfail"]
				  
		values = manager.query("node_config\n%s"%node)
		if values == None :
			values = ["" for i in range(8)]
		config = dict(zip(node_attr_names,values))
		
		return config

	def get_running_rsc(self, node) :
		return self.query("running_rsc\n%s"%node)	

	# resource functions
	def get_top_rsc(self) :
		ret = self.query("all_rsc")
		if ret == None:
			return []
		else:
			return ret

	def get_rsc_type(self, rsc_id) :
		rsc_type_ret = self.query("rsc_type\n"+str(rsc_id))
		if rsc_type_ret != None and len(rsc_type_ret) > 0 :
			rsc_type = rsc_type_ret[0]
		else :
			rsc_type = None

		if rsc_type == "native" :
			return "primitive"
		else :
			return rsc_type
	
	def get_rsc_status(self, rsc_id) :
		status = self.query("rsc_status\n"+rsc_id)
		for lrm_node in manager.xml_nodes["cib"].getElementsByTagName("lrm") :
			node_id = lrm_node.getAttribute("id")
			for lrm_resource_node in lrm_node.getElementsByTagName("lrm_resource") :
				if lrm_resource_node.getAttribute("id") == rsc_id :
					for lrm_rsc_op in lrm_resource_node.getElementsByTagName("lrm_rsc_op") :
						operation = lrm_rsc_op.getAttribute("operation")
						if lrm_rsc_op.getAttribute("op-status") == "-1" :
							if operation == "start" :
								status[0] = "starting"
								break
							elif operation == "stop" :
								status[0] = "stopping"
								break
		return status

	def get_rsc_running_on(self, rsc_id) :
		return self.query("rsc_running_on\n"+rsc_id)

	def get_sub_rsc(self, rsc_id) :
		sub_rscs = self.query("sub_rsc\n"+rsc_id)
		if sub_rscs != None :
			for sub_rsc in sub_rscs :
				self.parent[sub_rsc] = rsc_id
		else :
			return []
		return sub_rscs

	def get_all_subrsc(self, rsc_id) :
		all_subrscs = []
		sub_rscs = self.get_sub_rsc(rsc_id)
		if sub_rscs != None :
			for sub_rsc in sub_rscs :
				all_subrscs.append(sub_rsc)
				all_sub_subrscs = self.get_all_subrsc(sub_rsc)
				if all_sub_subrscs != None :
					all_subrscs.extend(all_sub_subrscs)
		return all_subrscs

	def get_all_rsc(self) :
		all_rscs = []
		top_rscs = self.query("all_rsc")
		if top_rscs != None :
			for top_rsc in top_rscs :
				all_rscs.append(top_rsc)
				all_subrscs = self.get_all_subrsc(top_rsc)
				if all_subrscs != None :
					all_rscs.extend(all_subrscs)
		return all_rscs

	def get_all_real_rsc(self) :
		all_rscs = self.get_all_rsc()
		all_real_rsc = []
		for rsc in all_rscs :
			rsc_real_id = self.obj_real_id(rsc)
			if all_real_rsc.count(rsc_real_id) == 0 :
				all_real_rsc.append(rsc_real_id)
		return all_real_rsc

	def get_all_real_subrsc(self, rsc_id) :
		all_subrscs = self.get_all_subrsc(rsc_id)
		all_real_subrsc = []
		for rsc in all_subrscs :
			rsc_real_id = self.obj_real_id(rsc)
			if all_real_subrsc.count(rsc_real_id) == 0 :
				all_real_subrsc.append(rsc_real_id)
		return all_real_subrsc

	def obj_real_id(self, obj_id) :
		return obj_id.split(":")[0]

	def op_status2str(self, op_status) :
		str_list = self.query("op_status2str\n%s"%str(op_status), True)
		if str_list != None and len(str_list) > 0 :
			return str_list[0]
		else :
			return ""

	def get_rsc_info(self, rsc_id) :
		for resources_node in manager.xml_nodes["cib"].getElementsByTagName("resources") :
			for primitive_node in resources_node.getElementsByTagName("primitive") :
				if primitive_node.getAttribute("id") == rsc_id :
					primitive_attrs = self.get_rsc_attrs(primitive_node, ["class", "type", "provider"])
                                        rsc_class = str(primitive_attrs.get("class", ""))
                                        rsc_type = str(primitive_attrs.get("type", ""))
                                        rsc_provider = str(primitive_attrs.get("provider", ""))
					return (rsc_class, rsc_type, rsc_provider)
		return None

	def get_rsc_attrs(self, primitive_node, attr_names) :
		attrs ={}

                ref_node = primitive_node
                while ref_node and ref_node.nodeType == xml.dom.Node.ELEMENT_NODE :
                        for attr_name in attr_names :
                                if attrs.get(attr_name) :
                                        continue
 
                                attr_value = ref_node.getAttribute(attr_name)
                                if attr_value :
                                        attrs[attr_name] = str(attr_value)

                        template_id = ref_node.getAttribute("template")
                        if template_id :
                                ref_node = self.get_template(template_id)
                        else :
                                break

                return attrs

        def get_template(self, template_id) :
                if not template_id :
                        return None

                for resources_node in manager.xml_nodes["cib"].getElementsByTagName("resources") :
                        for template_node in resources_node.getElementsByTagName("template") :
                                if template_node.getAttribute("id") == template_id :
                                        return template_node
                return None

        def get_all_templates(self) :
                templates = []
                for resources_node in manager.xml_nodes["cib"].getElementsByTagName("resources") :
                        for template_node in resources_node.getElementsByTagName("template") :
                                template_id = template_node.getAttribute("id")
                                if template_id and template_id not in templates:
                                        templates.append(template_id)
                return templates

	def get_locale_desc(self, node, tag) :
		desc_en = ""
		desc_match = ""
		
		(lang, encode) = locale.getlocale()
		if lang == None:
			lang = "en"
		else:
			lang = string.lower(lang)
		if encode == None:	
			encode = ""
		else:	
			encode = string.lower(encode)
		
		for child in node.childNodes :
			if child.nodeType != node.ELEMENT_NODE :
				continue
			if child.tagName != tag :
				continue
			if len(child.childNodes) == 0:
				break
			langtag = string.lower(child.getAttribute("lang"))
			if langtag == "" :
				desc_en = child.childNodes[0].data
			else :
				langtag = string.split(langtag, ".")
				if string.find(langtag[0], "en") != -1 :
					desc_en = child.childNodes[0].data
				if len(langtag) == 1 and lang == langtag[0] :
					desc_match = child.childNodes[0].data
				if len(langtag) == 2 :	
					if lang == langtag[0] and encode == langtag[1] :
						desc_match = child.childNodes[0].data	
		if desc_match != "" :
			return desc_match
		return desc_en				
		
			
	def get_rsc_meta(self, rsc_class, rsc_type, rsc_provider) :
		if rsc_class == None or rsc_class == "" \
				or rsc_type == None or rsc_type == "" :
			return None
		if rsc_provider == None or rsc_provider == "" :
			rsc_provider = "pacemaker" #"heartbeat"

		lines = self.query("rsc_metadata\n%s\n%s\n%s"% \
				(rsc_class, rsc_type, rsc_provider),True)
		if lines == None :
			return None
		meta_data = ""
		for line in lines :
			if len(line)!= 0 :
				meta_data = meta_data + line + "\n"
		try :
			doc_xml = parseString(meta_data).documentElement
		except xml.parsers.expat.ExpatError, msg :
			errmsg = "Failed to parse the metadata of %s: %s"
			log(errmsg%(rsc_type, msg))
			msgbox(top_window, _(errmsg)%(rsc_type, _(msg)))
			return None
			
		meta = RAMeta()
		meta.name = doc_xml.getAttribute("name")
		meta.version = ""
		version_xml = doc_xml.getElementsByTagName("version")
		if version_xml != [] and version_xml[0] in doc_xml.childNodes :
			meta.version = version_xml[0].childNodes[0].data

		meta.longdesc = self.get_locale_desc(doc_xml, "longdesc");
		meta.shortdesc = self.get_locale_desc(doc_xml, "shortdesc");
		
		meta.parameters = []
		for param_xml in doc_xml.getElementsByTagName("parameter") :
			param = {}
			param["name"] = param_xml.getAttribute("name")
			param["required"] = param_xml.getAttribute("required")
			param["unique"] = param_xml.getAttribute("unique")
			param["longdesc"] = self.get_locale_desc(param_xml, "longdesc");
			param["shortdesc"] = self.get_locale_desc(param_xml, "shortdesc");
			content_xml = param_xml.getElementsByTagName("content")[0]
			content = {}
			content["type"] = content_xml.getAttribute("type")
			content["default"] = content_xml.getAttribute("default")
			param["value"] = content["default"]
			param["content"] = content
			meta.parameters.append(param)
		meta.actions = []
		for action_xml in doc_xml.getElementsByTagName("action") :
			action = {}
			for key in action_xml.attributes.keys() :
				action[key] = action_xml.getAttribute(key)
			meta.actions.append(action)
		return meta
	
	def get_rsc_classes(self) :
		return self.query("rsc_classes",True);

	def get_rsc_types(self, rsc_class) :
		return self.query("rsc_types\n"+rsc_class,True)
	
	def get_rsc_providers(self, rsc_class, rsc_type) :
		return self.query("rsc_providers\n%s\n%s"%(rsc_class, rsc_type),True)

	def lrm_op_rc2str(self, rc) :
		str_list = self.query("lrm_op_rc2str\n%s"%str(rc), True)
		if str_list != None and len(str_list) > 0 :
			return str_list[0]
		else :
			return ""

	def rsc_exists(self, rsc_id) :
		return rsc_id in self.get_all_rsc()

class WidgetGroup :
	def __init__(self, widgets) :
		self.widgets = widgets

	def get_values(self) :
		object = {}
		widgets = self.widgets
		if widgets.has_key("value_labels") :
			for key in widgets["value_labels"].keys() :
				if widgets["value_labels"][key].get_property("sensitive") == False :
					continue
				object[key] = widgets["value_labels"][key].get_text()
				if object[key] == "" or object[key] == None :
					object.pop(key)
		if widgets.has_key("combos") :
			for key in widgets["combos"].keys() :
				if widgets["combos"][key].get_property("sensitive") == False :
					continue
				if pygtk_newer(2, 6) :
					object[key] = widgets["combos"][key].get_active_text()
				else :
					iter = widgets["combos"][key].get_active_iter()
					if iter != None :
						object[key] = widgets["combos"][key].get_model().get_value(iter, 0)
					else :
						object[key] = None
				if object[key] == "" or object[key] == None :
					object.pop(key)
		if widgets.has_key("bool_combos") :
			for key in widgets["bool_combos"].keys() :
				if widgets["bool_combos"][key].get_property("sensitive") == False :
					continue
				if pygtk_newer(2, 6) :
					object[key] = widgets["bool_combos"][key].get_active_text()
				else :
					iter = widgets["bool_combos"][key].get_active_iter()
					if iter != None :	
						object[key] = widgets["bool_combos"][key].get_model().get_value(iter, 0)
					else :
						object[key] = None
				if object[key] == "" or object[key] == None :
					object.pop(key)
		if widgets.has_key("combo_entries") :
			for key in widgets["combo_entries"].keys() :
				if widgets["combo_entries"][key].get_property("sensitive") == False :
					continue
				object[key] = widgets["combo_entries"][key].child.get_text()
				if object[key] == "" or object[key] == None :
					object.pop(key)
			# 修复无法创建service、fence和systemd资源的问题
                        if 'class' in object and object['class'] != 'ocf' and 'provider' in object:
                                object.pop('provider')

		if widgets.has_key("checkbuttons") :
			for key in widgets["checkbuttons"].keys() :
				if widgets["checkbuttons"][key].get_property("sensitive") == False :
					continue
				if widgets["checkbuttons"][key].get_active() :
					object[key] = "true"
				else:
					object[key] = "false"
		if widgets.has_key("entries") :
			for key in widgets["entries"].keys() :
				if widgets["entries"][key].get_property("sensitive") == False :
					continue
				object[key] = widgets["entries"][key].get_text()
				if object[key] == "" or object[key] == None :
					object.pop(key)
		if widgets.has_key("spinbuttons") :
			for key in widgets["spinbuttons"].keys() :
				if widgets["spinbuttons"][key].get_property("sensitive") == False :
					continue
				object[key] = str(int(widgets["spinbuttons"][key].get_value()))
				if object[key] == ""  or object[key] == None :
					object.pop(key)

		if widgets.has_key("anyname_combo_entries") :
			for key in widgets["anyname_combo_entries"].keys() :
				if widgets["anyname_combo_entries"][key].get_property("sensitive") == False :
					continue
				attr_name = key.get_text()
				object[attr_name] = widgets["anyname_combo_entries"][key].child.get_text()
				if attr_name == "" or object[attr_name] == "" or object[attr_name] == None :
					object.pop(attr_name)

		if widgets.has_key("radiobuttons") :
			for key in widgets["radiobuttons"].keys() :
				if widgets["radiobuttons"][key].get_property("sensitive") == False :
					continue
				if widgets["radiobuttons"][key].get_active() :
					object[key] = "true"
				else:
					object[key] = "false"

		return object

	def show_values(self, object) :
		widgets = self.widgets
		if widgets.has_key("value_labels") :
			for key in widgets["value_labels"].keys() :
				if object.has_key(key) :
					widgets["value_labels"][key].set_text(object[key])

		if widgets.has_key("combos") :
 			for key in widgets["combos"].keys() :
				if object.has_key(key) :
					iter = widgets["combos"][key].get_model().get_iter_first()
					while iter != None :
						if widgets["combos"][key].get_model().get_value(iter,0) == object[key] :
							widgets["combos"][key].set_active_iter(iter)

						#neoshineha ming.liu add
						if key == str("class") and object[key] == "" and widgets["combos"][key].get_model().get_value(iter,0) == str("ocf"):
							widgets["combos"][key].set_active_iter(iter)
						#neoshineha add end
						iter = widgets["combos"][key].get_model().iter_next(iter)
				else :
					widgets["combos"][key].set_active(0)

		if widgets.has_key("bool_combos") :
 			for key in widgets["bool_combos"].keys() :
				if object.has_key(key) :
					if object[key] == "true" or object[key] == "yes" or object[key] == "1" :
						bool_value = "true"
					elif object[key] == "false" or object[key] == "no" or object[key] == "0" :
						bool_value = "false"
					else :
						bool_value = object[key]
					iter = widgets["bool_combos"][key].get_model().get_iter_first()
					while iter != None :
						if widgets["bool_combos"][key].get_model().get_value(iter,0) == bool_value :
							widgets["bool_combos"][key].set_active_iter(iter)
						iter = widgets["bool_combos"][key].get_model().iter_next(iter)
				else :
					widgets["bool_combos"][key].set_active(0)
			
		if widgets.has_key("combo_entries") :
 			for key in widgets["combo_entries"].keys():
				if object.has_key(key) :
					widgets["combo_entries"][key].child.set_text(object[key])
					#neoshineha add
					if key == str("provider") and object[key] == "":
						#widgets["combo_entries"][key].child.set_text("heartbeat")
						widgets["combo_entries"][key].child.set_text("pacemaker")
					#neoshineha
				else :
					widgets["combo_entries"][key].child.set_text("")

		if widgets.has_key("entries") :
			for key in widgets["entries"].keys() :
				if object.has_key(key) :
					widgets["entries"][key].set_text(object[key])
				else :
					widgets["entries"][key].set_text("")

		if widgets.has_key("checkbuttons") :
			for key in widgets["checkbuttons"].keys() :
				if object.has_key(key) :
					lower_value = object[key].lower()
					widgets["checkbuttons"][key].set_active("true" == lower_value
										or "yes" == lower_value
										or "1" == lower_value)
		if widgets.has_key("spinbuttons") :
			for key in widgets["spinbuttons"].keys() :
				if object.has_key(key) :
					try :
						widgets["spinbuttons"][key].set_value(float(object[key]))
					except :
						pass

		if widgets.has_key("anyname_combo_entries") :
			for key in widgets["anyname_combo_entries"].keys() :
				attr_name = key.get_text()
				if object.has_key(attr_name) :
					widgets["anyname_combo_entries"][key].child.set_text(object[attr_name])
				else :
					widgets["anyname_combo_entries"][key].child.set_text("")

class ObjectAttrs(WidgetGroup) :
	dynamic_layout = None
	dynamic_fill = None
	dynamic_desc = None
	static_desc = None
	dynamic_render = None
	dynamic_set_id = None
	save_id = None

	def __init__(self, xml_node, is_newobj = False, change_call_back = None, hide_optional = False) :
		self.xml_node = xml_node
		self.obj_type = xml_node.tagName
		self.is_newobj = is_newobj
		self.change_call_back = change_call_back
		self.hide_optional = hide_optional
		self.render_attrs_vbox()

		if validate_type == "dtd" :
			self.dtd_elem = manager.get_dtd_elem(self.obj_type)
			self.attr_list = dtd_elem.get_attr_list()
			if self.dtd_elem.get_content_model()[1] == [] :
				self.auto_id = True
				self.dynamic_set_id = self.dynamic_set_id_auto
			else :
				self.auto_id = False
			self.render_widgets_dtd()
		else :
			self.render_widgets_rng()

		for widget_type in ("combos", "bool_combos", "combo_entries") :
			if self.widgets.has_key(widget_type) :
				for widget in self.widgets[widget_type].values() :
					if pygtk_newer(2, 10) and pygobject_newer(2, 12, 3) :
						widget.connect("changed", self.on_changed)
					else :
						widget.connect("changed", self.on_changed_later)
						

		for widget in self.widgets.get("anyname_combo_entries", {}) :
			if pygtk_newer(2, 10) and pygobject_newer(2, 12, 3) :
				widget.connect("changed", self.on_changed)
				self.widgets["anyname_combo_entries"][widget].connect("changed", self.on_changed)
			else :
				widget.connect("changed", self.on_changed_later)
				self.widgets["anyname_combo_entries"][widget].connect("changed", self.on_changed_later)

	def verify_values(self) :
		if validate_type == "dtd" :
			return self.verify_values_dtd()
		else :
			return self.verify_values_rng()

	def on_after_show(self) :
		if self.auto_id or (mode_level == 0 and self.dynamic_set_id != None) :
			self.hide_id_widget()

		if self.auto_id == True :
			if self.is_newobj :
				if self.widgets.has_key("combo_entries") and self.widgets["combo_entries"].has_key("id") :
					if len(self.widgets["combo_entries"]["id"].child.get_text()) == 0 :
						#self.widgets["combo_entries"]["id"].child.set_text(self.obj_type + "-" + gen_uuid())
                                                obj_id = manager.auto_unique_id(self.xml_node, self.obj_type)
                                                self.widgets["combo_entries"]["id"].child.set_text(obj_id)
		#			self.widgets["name_labels"]["id"].hide_all()
		#			self.widgets["combo_entries"]["id"].hide_all()
		#	else :
		#		if self.widgets.has_key("name_labels") and self.widgets["name_labels"].has_key("id") :
		#			self.widgets["name_labels"]["id"].hide_all()
		#			self.widgets["value_labels"]["id"].hide_all()

		else :
			if self.is_newobj and not self.id_is_idref and self.obj_type not in \
					["node", "primitive", "template", "group", "clone", "master","master_slave", \
					"rsc_location", "rsc_colocation", "rsc_order", "rsc_ticket", "acl_user", "acl_role"] :
				if self.widgets.has_key("combo_entries") and self.widgets["combo_entries"].has_key("id") \
						and len(self.widgets["combo_entries"]["id"].child.get_text()) == 0 :
					obj_id = manager.auto_unique_id(self.xml_node, self.obj_type)
					self.widgets["combo_entries"]["id"].child.set_text(obj_id)
		#			parent_id = self.xml_node.parentNode.getAttribute("id")
		#			if parent_id == "" :
		#				id_prefix = self.obj_type
		#			else :
		#				id_prefix = parent_id + "-" + self.obj_type
		#			self.widgets["combo_entries"]["id"].child.set_text(id_prefix)

		if self.pref_expand and (mode_level != 0 or self.obj_type not in ["op", "rsc_order"] ) :
			self.optional_expander.set_expanded(True)

		self.auto_fill()

		if len(self.required_vbox.get_children()) < 2 :
			self.required_vbox.hide()

		if len(self.optional_vbox.get_children()) < 1 or self.hide_optional :
			self.optional_expander.hide()

		if self.dynamic_desc == None and self.static_desc == None :
			#self.vbox_labels["Description"].hide()
			self.desc_outer_vbox.hide()

		if self.static_desc != None :
			self.show_desc(self.static_desc)

		if not pygtk_newer(2, 10) or not pygobject_newer(2, 12, 3) :
			return

		for widget_type in ("combos", "bool_combos", "combo_entries") :
			if self.widgets.has_key(widget_type) :
				for widget in self.widgets[widget_type].values() :
					widget.disconnect_by_func(self.on_changed)
					widget.connect("changed", self.on_changed_later)

		for widget in self.widgets.get("anyname_combo_entries", {}) :
			widget.disconnect_by_func(self.on_changed)
			widget.connect("changed", self.on_changed_later)
			self.widgets["anyname_combo_entries"][widget].disconnect_by_func(self.on_changed)
			self.widgets["anyname_combo_entries"][widget].connect("changed", self.on_changed_later)

	def render_attrs_vbox(self) :
		required_vbox = gtk.VBox()
		optional_vbox = gtk.VBox()
		optional_expander = gtk.Expander()
		optional_expander.add(optional_vbox)

		desc_outer_vbox = gtk.VBox()
		widget_list = [(required_vbox, "Required"), 
				(optional_expander, "Optional"),
				(desc_outer_vbox, "Description")]
		self.vbox_labels = {}
		for (widget, label_text) in widget_list : 
			vbox_label = gtk.Label()
			vbox_label.set_markup('<b>' + _(label_text) + '</b>')
			vbox_label.set_alignment(0, 1)
			if label_text == "Optional" :
				widget.set_label_widget(vbox_label)
			else :
				widget.pack_start(vbox_label, False, padding=2)
			self.vbox_labels[label_text] = vbox_label

		desc_vbox = gtk.VBox()
		desc_sw = gtk.ScrolledWindow()
		desc_sw.set_shadow_type(gtk.SHADOW_NONE)
		desc_sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		desc_sw.add_with_viewport(desc_vbox)
		desc_sw.child.set_shadow_type(gtk.SHADOW_NONE)
		desc_outer_vbox.pack_start(desc_sw)
		desc_outer_vbox.set_size_request(380, 100)

		attrs_vbox = gtk.VBox()
		for (widget, label_text) in widget_list :
			if label_text == "Description" :
				attrs_vbox.pack_start(widget, True, padding = 2)
			else :
				attrs_vbox.pack_start(widget, False, padding = 2)

		self.attrs_vbox = attrs_vbox
		self.required_vbox = required_vbox
		self.optional_vbox = optional_vbox
		self.optional_expander = optional_expander
		self.desc_outer_vbox = desc_outer_vbox
		self.desc_vbox = desc_vbox

	def render_widgets_dtd(self):
		obj_type = self.obj_type
		is_newobj = self.is_newobj
		required_vbox = self.required_vbox
		optional_vbox = self.optional_vbox
		attrs_vbox = self.attrs_vbox

		dtd_elem = self.dtd_elem

		widgets = {}
		name_labels = {}
		value_labels = {}
		combos = {}
		bool_combos = {}
		combo_entries = {}
		required_row = 0
		optional_row = 0
		name_label_max_len = 0

		self.hboxes = {}
		for attr_name in self.attr_list :
			attr = dtd_elem.get_attr(attr_name)
			label_text = _(name_cap(attr_name)) + _(":")
			label = gtk.Label(label_text)
			label.set_alignment(0, 0.5)
			label_len = label.size_request()[0]
			if label_len > name_label_max_len :
				name_label_max_len = label_len
			eventbox = gtk.EventBox()
			eventbox.add(label)
			name_labels[attr_name] = label

			attr_type = attr.get_type()
			attr_default = attr.get_default()
			attr_decl = attr.get_decl()
			
			if attr_name == "id" and is_newobj == False :
				widget = gtk.Label()
				widget.set_alignment(0, 0.5)
				value_labels[attr_name] = widget
			elif type(attr_type) == list:
				is_boolean = False
				store = gtk.ListStore(str, str)
				if attr_decl != "#REQUIRED" :
					store.append(["", ""])
				if attr_type.count("true") > 0 and attr_type.count("false") > 0 :
					options = ("true", "false")
					is_boolean = True
				else: 
					options = attr_type
					
				for option in options:
					if attr_default != None and option == attr_default :
						store.append([option, "["+_("default")+"]"])
					else :
						store.append([option, ""])
				widget = gtk.ComboBox(store)
				cell0 = gtk.CellRendererText()
				cell1 = gtk.CellRendererText()
				widget.pack_start(cell0, True)
				widget.pack_start(cell1, True)
				widget.add_attribute(cell0, 'text', 0)
				widget.add_attribute(cell1, 'text', 1)
				if is_boolean == False :
					combos[attr_name] = widget
				else :
					bool_combos[attr_name] = widget
			else :
				store = gtk.ListStore(str, str)
				if attr_decl != "#REQUIRED" :
					store.append(["", ""])
				if attr_default != None :
					store.append([attr_default, "["+_("default")+"]"])
				widget = gtk.ComboBoxEntry(store)
				cell = gtk.CellRendererText()
				widget.pack_start(cell, True)
				widget.add_attribute(cell, 'text', 1)
				widget.child.set_activates_default(True)
				combo_entries[attr_name] = widget

			
			hbox = gtk.HBox()
			hbox.pack_start(eventbox, False, padding=5)
			hbox.pack_start(widget, padding=5)

			if attr_decl == "#REQUIRED":
				required_vbox.pack_start(hbox, False, padding=2)
			else:
				optional_vbox.pack_start(hbox, False, padding=2)

			self.hboxes[attr_name] = hbox

		attrs_vbox.show_all()

		for name_label in name_labels.values() :
			name_label.set_size_request(name_label_max_len, -1)
		
		widgets["name_labels"] = name_labels
		widgets["value_labels"] = value_labels
		widgets["combos"] = combos
		widgets["bool_combos"] = bool_combos
		widgets["combo_entries"] = combo_entries

		self.widgets = widgets

	def verify_values_dtd(self) :
		widgets = self.widgets
		obj_type = self.obj_type
		passed = True
		dtd_elem = self.dtd_elem
		object = self.get_values()

		for attr_name in self.attr_list :
			attr = dtd_elem.get_attr(attr_name)
			attr_decl = attr.get_decl()
			
			if attr_decl == "#REQUIRED" and not object.has_key(attr_name) :
				msgbox(top_window, _(name_cap(attr_name)) + (":")+_(" can't be empty"))
				passed =False
		return passed

	def render_widgets_rng(self):
		obj_type = self.obj_type
		is_newobj = self.is_newobj
		required_vbox = self.required_vbox
		optional_vbox = self.optional_vbox
		attrs_vbox = self.attrs_vbox

		widgets = {}
		name_labels = {}
		value_labels = {}
		combos = {}
		bool_combos = {}
		combo_entries = {}
		required_row = 0
		optional_row = 0
		name_label_max_len = 0


		self.attr_rng_node_dict = {}
		self.elem_rng_node_dict = {}
		attr_is_any_name = False
		any_attr_decl = []
		elem_is_any_name = False
		attr_list = []
		elem_type_list = []
		id_is_idref = False
		sorted_rng_nodes = manager.sorted_sub_rng_nodes_by_name(self.obj_type)
		if sorted_rng_nodes != None :
			attr_rng_nodes = sorted_rng_nodes.get("attribute", [])
			elem_rng_nodes = sorted_rng_nodes.get("element", [])
			for rng_node in attr_rng_nodes :
				name = rng_node[0][1].getAttribute("name")
				if name == "" :
					attr_is_any_name = True
					for decl in ["optional", "zeroOrMore", "oneOrMore"] :
						if manager.find_decl(rng_node, decl) != 0 :
							any_attr_decl.append(decl)
				else:
					if attr_list.count(name) == 0 :
						attr_list.append(name)
						self.attr_rng_node_dict[name] = []
						if name == "id" :
							sub_rng_nodes = manager.sorted_sub_rng_nodes_by_node(*rng_node[0])
							for sub_rng_node in sub_rng_nodes.get("data", []) :
								if sub_rng_nodes["data"][0][0][1].getAttribute("type") == "IDREF" :
									id_is_idref = True
									break
					self.attr_rng_node_dict[name].append(rng_node)

			for rng_node in elem_rng_nodes :
				name = rng_node[0][1].getAttribute("name")
				if name == "" :
					elem_is_any_name = True
				else :
					if elem_type_list.count(name) == 0 :
						elem_type_list.append(name)
						self.elem_rng_node_dict[name] = []
					self.elem_rng_node_dict[name].append(rng_node)
		else :
			attr_is_any_name = True
			any_attr_decl.append("zeroOrMore")
			elem_is_any_name = True
			attr_rng_nodes = []
			elem_rng_nodes = None

		self.attr_list = attr_list
		self.any_attr_decl = any_attr_decl
		self.attr_rng_nodes = attr_rng_nodes
		self.id_is_idref = id_is_idref

		other_attrs = []
		if attr_is_any_name :
			for attr_name in self.xml_node.attributes.keys() :
				if attr_list.count(attr_name) == 0 :
					if attr_name == "id" :
						other_attrs.insert(0, attr_name)
					else :
						other_attrs.append(attr_name)
		attr_list.extend(other_attrs)

		if  any_attr_decl.count("zeroOrMore") or any_attr_decl.count("oneOrMore") :
			other_attrs.append("")

		if elem_rng_nodes == [] and not id_is_idref :
			self.auto_id = True
			self.dynamic_set_id = self.dynamic_set_id_auto
		else :
			self.auto_id = False
					
		sub_elem_node_list = []
		for child_node in self.xml_node.childNodes :
			if child_node.nodeType != xml.dom.Node.ELEMENT_NODE :
				continue
			sub_elem_node_list.append(child_node)
			
		if len(sub_elem_node_list) == 0 : 
			self.pref_expand = True
		else :
			self.pref_expand = False

		self.hboxes = {}
		store_list = {}
		for attr_node in attr_rng_nodes :
			attr_name = attr_node[0][1].getAttribute("name")
			if attr_name == "" :
				continue

			sub_rng_nodes = manager.sorted_sub_rng_nodes_by_node(*attr_node[0])
			if store_list.get(attr_name) != None :
				if len(sub_rng_nodes.get("value",[])) > 0 :
					for value_node in sub_rng_nodes["value"] :
						#neokylinha add
						if attr_name == str("class"):
							if value_node[0][1].childNodes[0].data == str("heartbeat") or value_node[0][1].childNodes[0].data == str("upstart"):
								continue
						#neokylinha add end
						store_list[attr_name].append([value_node[0][1].childNodes[0].data, ""])
				for sub_rng_node in sub_rng_nodes.get("data", []) :
					if sub_rng_nodes["data"][0][0][1].getAttribute("type") == "boolean" :
						for option in ("true", "false") :
							store_list[attr_name].append([option, ""])
				continue

			#neokylinha add
			if name_cap(attr_name) == "Provider":
				label_text = _("Type") + _(":")
			elif name_cap(attr_name) == "Type":
				label_text = _("Resources")+_(":")
			else:
				label_text = _(name_cap(attr_name)) + _(":")
			#neokylinha add end

			label = gtk.Label(label_text)
			label.set_alignment(0, 0.5)
			label_len = label.size_request()[0]
			if label_len > name_label_max_len :
				name_label_max_len = label_len
			eventbox = gtk.EventBox()
			eventbox.add(label)
			name_labels[attr_name] = label

			if attr_name == "id" and not id_is_idref and is_newobj == False :
				widget = gtk.Label()
				widget.set_alignment(0, 0.5)
				value_labels[attr_name] = widget
			elif len(sub_rng_nodes.get("value",[])) > 0 \
					and len(sub_rng_nodes.get("data", [])) == 0 \
					and len(sub_rng_nodes.get("text", [])) == 0 :
				store = gtk.ListStore(str, str)
				store_list[attr_name] = store
				if manager.find_decl(attr_node, "optional") != 0 :
					store.append(["", ""])

				for value_node in sub_rng_nodes["value"] :
					store.append([value_node[0][1].childNodes[0].data, ""])

				#for option in options:
				#	if attr_default != None and option == attr_default :
				#		store.append([option, "["+_("default")+"]"])
				#	else :
				#		store.append([option, ""])

				widget = gtk.ComboBox(store)
				cell0 = gtk.CellRendererText()
				cell1 = gtk.CellRendererText()
				widget.pack_start(cell0, True)
				widget.pack_start(cell1, True)
				widget.add_attribute(cell0, 'text', 0)
				widget.add_attribute(cell1, 'text', 1)
				combos[attr_name] = widget

			elif len(sub_rng_nodes.get("data",[])) == 1 \
					and sub_rng_nodes["data"][0][0][1].getAttribute("type") == "boolean" \
					and len(sub_rng_nodes.get("text", [])) == 0 :
				store = gtk.ListStore(str, str)
				store_list[attr_name] = store
				if manager.find_decl(attr_node, "optional") != 0 :
					store.append(["", ""])

				for option in ("true", "false") :
					store.append([option, ""])

				if len(sub_rng_nodes.get("value",[])) > 0 :
					for value_node in sub_rng_nodes["value"] :
						store.append([value_node[0][1].childNodes[0].data, ""])

				widget = gtk.ComboBox(store)
				cell0 = gtk.CellRendererText()
				cell1 = gtk.CellRendererText()
				widget.pack_start(cell0, True)
				widget.pack_start(cell1, True)
				widget.add_attribute(cell0, 'text', 0)
				widget.add_attribute(cell1, 'text', 1)
				bool_combos[attr_name] = widget

			else :
				store = gtk.ListStore(str, str)
				store_list[attr_name] = store
				if manager.find_decl(attr_node, "optional") != 0 :
					store.append(["", ""])
				#if attr_default != None :
				#	store.append([attr_default, "["+_("default")+"]"])
				if len(sub_rng_nodes.get("value",[])) > 0 :
					for value_node in sub_rng_nodes["value"] :
						store.append([value_node[0][1].childNodes[0].data, ""])

				for sub_rng_node in sub_rng_nodes.get("data", []) :
					if sub_rng_nodes["data"][0][0][1].getAttribute("type") == "boolean"  :
						for option in ("true", "false") :
							store.append([option, ""])

				widget = gtk.ComboBoxEntry(store)
				cell = gtk.CellRendererText()
				widget.pack_start(cell, True)
				widget.add_attribute(cell, 'text', 1)
				widget.child.set_activates_default(True)
				combo_entries[attr_name] = widget
			
			#neoshineha add ming.liu
			if self.obj_type == "primitive" and (attr_name == "provider" or attr_name == "type"): 
				widget.child.set_editable(False)
			#neoshineha add end

			hbox = gtk.HBox()
			hbox.pack_start(eventbox, False, padding=5)
			hbox.pack_start(widget, padding=5)

			if manager.find_decl(attr_node, "optional") == 0 :
				required_vbox.pack_start(hbox, False, padding=2)
			else:
				optional_vbox.pack_start(hbox, False, padding=2)

			self.hboxes[attr_name] = hbox

		anyname_combo_entries = {}
		for attr_name in other_attrs :
			(name_entry, widget) = self.render_anyname_widgets(attr_name)
			anyname_combo_entries[name_entry] = widget

		attrs_vbox.show_all()

		for name_label in name_labels.values() :
			name_label.set_size_request(name_label_max_len, -1)
		
		widgets["name_labels"] = name_labels
		widgets["value_labels"] = value_labels
		widgets["combos"] = combos
		widgets["bool_combos"] = bool_combos
		widgets["combo_entries"] = combo_entries
		widgets["anyname_combo_entries"] = anyname_combo_entries

		self.widgets = widgets

	def render_anyname_widgets(self, attr_name) :
		any_attr_decl = self.any_attr_decl
		name_entry = gtk.Entry()
		name_entry.set_text(attr_name)
		name_entry.set_activates_default(True)

		label = gtk.Label(_(":"))

		store = gtk.ListStore(str, str)
		widget = gtk.ComboBoxEntry(store)
		cell = gtk.CellRendererText()
		widget.pack_start(cell, True)
		widget.add_attribute(cell, 'text', 1)
		widget.child.set_activates_default(True)

		hbox = gtk.HBox()
		hbox.pack_start(name_entry, False, padding=5)
		hbox.pack_start(label, False)
		hbox.pack_start(widget, padding=5)

		if any_attr_decl.count("optional") or any_attr_decl.count("zeroOrMore") :
			self.optional_vbox.pack_start(hbox, False, padding=2)
		elif any_attr_decl.count("oneOrMore") and len(self.widgets.get("anyname_combo_entries", {})) > 0:
			self.optional_vbox.pack_start(hbox, False, padding=2)
		else :
			self.required_vbox.pack_start(hbox, False, padding=2)

		hbox.show_all()

		return (name_entry, widget)

	def verify_values_rng(self) :
		widgets = self.widgets
		obj_type = self.obj_type
		passed = True
		object = self.get_values()

		choice_attrs = []
		for attr_node in self.attr_rng_nodes :
			attr_name = attr_node[0][1].getAttribute("name")

			attr_value = object.get(attr_name)
			#neoshineha begin
			if obj_type == "primitive" and attr_name == "type" and attr_value == "drbd" and len(manager.get_normal_nodes()) != 2:
				msgbox(top_window, _("The resource drbd can only be run in two-node cluster!"))
				passed = False
			#neoshineha

			if attr_value !=  None and manager.get_rng_attr_type(attr_node) in ["ID", "IDREF"]:
				if not is_valid_id(attr_value) :
					msgbox(top_window, _(name_cap(attr_name))+ _(": ")+_("Invalid identifier \"%s\"")%attr_value)
					passed = False

			if object.has_key(attr_name) or manager.find_decl(attr_node, "optional") != 0 \
					or manager.find_decl(attr_node, "zeroOrMore") != 0 :
				continue

			if manager.find_decl(attr_node, "choice") == 0  :
				#neokylinha add
				if name_cap(attr_name) == "Type":
					msgbox(top_window, _("Resources")+ _(":")+_(" can't be empty"))
				else:
					msgbox(top_window, _(name_cap(attr_name))+ _(":")+_(" can't be empty"))
				#neokylinha add end
				passed = False
			else :
				choice_attrs.append(attr_node)

		return passed

	def combobox_store_append(self, combo, append_options) :
		current_store = combo.get_model()
		retained_store = []
		for i in range(len(current_store)) :
			if current_store[i][0] == "" :
				retained_store.insert(0, current_store[i])
			elif current_store[i][1] == "["+_("default")+"]" :
				retained_store.append(current_store[i])
			
		new_store = gtk.ListStore(str, str)
		for retained in retained_store :
			new_store.append(retained)
		retained_list = [k[0] for k in retained_store]
		for append_option in append_options :
			if retained_list.count(append_option[0]) == 0 :
				new_store.append(append_option)
		combo.set_model(new_store)

	def auto_fill(self) :
		widgets = self.widgets
		rsc_store = gtk.ListStore(str, str)
		#all_real_rsc = manager.get_all_real_rsc()
		all_real_rsc = manager.get_top_rsc()
		for rsc in all_real_rsc :
			rsc_store.append([rsc, ""])

		node_list = manager.get_normal_nodes()
		if node_list == None :
			node_list = []
		node_store = [[node, ""] for node in node_list]

                all_templates = manager.get_all_templates()
                template_store = [[template, ""] for template in all_templates]

                rsc_refs = all_real_rsc[:]
                rsc_refs.extend(all_templates)
                rsc_refs_store = [[rsc, ""] for rsc in rsc_refs]
                rsc_refs_co_store = [[rsc, ""] for rsc in rsc_refs if manager.get_rsc_type(rsc) not in ["master","clone"]]

		if widgets.has_key("combo_entries") :
			for key in ["rsc", "with-rsc", "first", "then", "from", "to"] :
				if widgets["combo_entries"].has_key(key) :
					if self.obj_type == "rsc_location" :
                                                self.combobox_store_append(widgets["combo_entries"][key], rsc_store)
					elif self.obj_type == "rsc_colocation" :
						self.combobox_store_append(widgets["combo_entries"][key], rsc_refs_co_store)
                                        else :
                                                self.combobox_store_append(widgets["combo_entries"][key], rsc_refs_store)
			if widgets["combo_entries"].has_key("id") and self.id_is_idref :
				self.combobox_store_append(widgets["combo_entries"]["id"], rsc_store)

                        for key in ["template"] :
                                if widgets["combo_entries"].has_key(key) :
                                        self.combobox_store_append(widgets["combo_entries"][key], template_store)

			for key in ["node"] :
				if widgets["combo_entries"].has_key(key) :
					self.combobox_store_append(widgets["combo_entries"][key], node_store)
					
                        if widgets["combo_entries"].has_key("role-ref") :
                                acl_roles = []
                                for acls in manager.xml_nodes["cib"].getElementsByTagName("acls") :
                                        for acl_role in acls.getElementsByTagName("acl_role") :
                                                acl_role_id = acl_role.getAttribute("id")
                                                if acl_role_id != "" and acl_roles.count(acl_role_id) == 0 :
                                                        acl_roles.append(acl_role_id)
                                acl_role_store = [[acl_role, ""] for acl_role in acl_roles]
                                self.combobox_store_append(widgets["combo_entries"]["role-ref"], acl_role_store)

		role_attr_type = None
		if validate_type == "dtd" :
			try :
				op_dtd_elem = manager.get_dtd_elem("op")
				role_attr = op_dtd_elem.get_attr("role")
				role_attr_type = role_attr.get_type()
			except KeyError :
				pass

		if role_attr_type != None and type(role_attr_type) == list :
			roles = role_attr_type
		else :
			roles = ["Master", "Slave", "Started", "Stopped"]

		role_store = [[role, ""] for role in roles]
		if widgets.has_key("combo_entries") :
			for key in ["role", "from_role", "to_role"] :
				if widgets["combo_entries"].has_key(key) :
					self.combobox_store_append(widgets["combo_entries"][key], role_store)

		if validate_type != "dtd" :
			return

		scores = ["INFINITY", "-INFINITY"]
		score_store = [[score, ""] for score in scores]
		if widgets.has_key("combo_entries") and widgets["combo_entries"].has_key("score") :
			self.combobox_store_append(widgets["combo_entries"]["score"], score_store)


	def on_changed(self, widget) :
		if self.dynamic_layout != None :
			self.dynamic_layout(widget)

		if self.dynamic_choice != None and validate_type != "dtd" :
			self.dynamic_choice(widget)

		if self.dynamic_fill != None :
			self.dynamic_fill(widget)
		if self.dynamic_desc != None :
			desc = self.dynamic_desc(widget)
			if desc != None :
				self.show_desc(desc)

		self.save()

	def on_changed_later(self, widget) :
		if self.dynamic_layout != None :
			self.dynamic_layout(widget)

		if self.dynamic_choice != None and validate_type != "dtd" :
			self.dynamic_choice(widget)

		if self.dynamic_fill != None :
			self.dynamic_fill(widget)
		if self.dynamic_desc != None :
			desc = self.dynamic_desc(widget)
			if desc != None :
				self.show_desc(desc)
		if self.change_call_back != None :
			self.change_call_back()

		if self.dynamic_render != None :
			self.dynamic_render(widget)

		if self.dynamic_set_id != None :
			self.dynamic_set_id(widget)

		save_id = self.xml_node.getAttribute("id")
		if save_id != "" :
			self.save_id = save_id

		self.save()

		new_id = self.xml_node.getAttribute("id")
		if self.save_id != None and new_id != "" and new_id != self.save_id :
			self.auto_change_child_ids(self.xml_node, new_id)

	def auto_change_child_ids(self, xml_node, new_id) :
		for child_node in xml_node.childNodes :
			if child_node.nodeType != xml.dom.Node.ELEMENT_NODE :
				continue
			id = child_node.getAttribute("id")
			if id.count(self.save_id + "-") > 0 :
				child_node.setAttribute("id", id.replace(self.save_id + "-", new_id + "-"))
			self.auto_change_child_ids(child_node, new_id)

	def dynamic_render(self, widget) :
		if widget in self.widgets.get("anyname_combo_entries", {}) :
			changed_attr_name = widget.get_text()
			if len(changed_attr_name) > 0 :
				need_add = True
				for name_widget in self.widgets["anyname_combo_entries"] :
					if name_widget.get_text() == "" :
						need_add = False
						break
				if need_add :
					(name_entry, widget) = self.render_anyname_widgets("")
					self.widgets["anyname_combo_entries"][name_entry] = widget
					name_entry.connect("changed", self.on_changed_later)
					widget.connect("changed", self.on_changed_later)

	def show_desc(self, desc) :
		widgets = self.widgets
		desc_vbox = self.desc_vbox

		if not widgets.has_key("desc_labels") :
			desc_labels = []
			for row in range(len(desc)) :
				desc_label = gtk.Label(desc[row])
				desc_label.set_alignment(0, 0.5)
				desc_label.set_padding(5, 0)
				desc_label.set_line_wrap(True)
				desc_label.set_selectable(True)
				desc_vbox.pack_start(desc_label, False, padding=2)
				desc_labels.append(desc_label)
			if desc_labels != [] :
				widgets["desc_labels"] = desc_labels
		else :
			for row in range(len(desc)) :
				widgets["desc_labels"][row].set_text(desc[row])
		desc_vbox.show_all()

	def update(self, xml_node = None) :
		if xml_node != None :
			self.xml_node = xml_node
		object_attrs = {}
		for attr_name in self.attr_list :
			attr_value = self.xml_node.getAttribute(attr_name)
			if attr_value != None :
				object_attrs[attr_name] = attr_value

		self.show_values(object_attrs)

	def save(self) :
		object_attrs = self.get_values()
		for attr_name in object_attrs :
			self.xml_node.setAttribute(attr_name, object_attrs.get(attr_name , ""))

		for attr_name in self.xml_node.attributes.keys() :
			if object_attrs.get(attr_name) == None :
				self.xml_node.removeAttribute(attr_name)

	def save_status(self) :
		return self.optional_expander.get_expanded()

	def restore_status(self, saved_status) :
		self.optional_expander.set_expanded(saved_status)

	def get_score(self, score_str) :
		try :
			score = int(score_str)
		except :
			if score_str in ["INFINITY", "infinity", "+INFINITY", "+infinity"] :
				score = 1000000
			elif score_str in ["-INFINITY", "-infinity"] :
				score = -1000000
			else :
				score = 0
		return score

	def dynamic_choice(self, widget) :
		widgets = self.widgets
		attr_rng_node_dict = self.attr_rng_node_dict
		attr_name = None
		for widget_type in widgets :
			if type(widgets[widget_type]) != dict :
				continue
			for key in widgets[widget_type] :
				if widgets[widget_type][key] == widget :
					attr_name = key
					break

		if attr_name == None :
			return

		attr_rng_nodes = attr_rng_node_dict.get(attr_name)
		if attr_rng_nodes == None :
			return

		object_attrs = self.get_values()

		ref_match_value_decl_nodes_list = []
		ref_decl_nodes_list = []
		for key in object_attrs :
			for attr_rng_node in attr_rng_node_dict.get(key, []) :
				decl_rng_nodes = manager.get_decl_rng_nodes(attr_rng_node)
				value_list = []
				sub_rng_nodes = manager.sorted_sub_rng_nodes_by_node(*attr_rng_node[0])
				for value_node in sub_rng_nodes.get("value", []) :
					value_list.append(value_node[0][1].childNodes[0].data)
				if object_attrs.get(key, "") in value_list :
					ref_match_value_decl_nodes_list.append(decl_rng_nodes)
				elif len(sub_rng_nodes.get("data", [])) > 0 or len(sub_rng_nodes.get("text", [])) > 0 :
					ref_decl_nodes_list.append(decl_rng_nodes)

		if len(ref_match_value_decl_nodes_list) > 0 :
			ref_decl_nodes_list = ref_match_value_decl_nodes_list

		ref_sorted_nodes = {}
		for decl_type in ["choice", "first_choice", "group", "first_group"] :
			ref_sorted_nodes[decl_type] = manager.get_sorted_decl_nodes(ref_decl_nodes_list, decl_type)
			
		match_value_decl_nodes_list = []
		decl_nodes_list = []
		for attr_rng_node in attr_rng_nodes :
			decl_rng_nodes = manager.get_decl_rng_nodes(attr_rng_node)
			if decl_rng_nodes.get("choice") == None :
				return

			if decl_rng_nodes.get("choice") in ref_sorted_nodes["choice"] and \
					decl_rng_nodes.get("group") != None and \
					len(ref_sorted_nodes["group"]) > 0 and \
					decl_rng_nodes.get("group") not in ref_sorted_nodes["group"] :
				continue

			value_list = []
			sub_rng_nodes = manager.sorted_sub_rng_nodes_by_node(*attr_rng_node[0])
			for value_node in sub_rng_nodes.get("value", []) :
				value_list.append(value_node[0][1].childNodes[0].data)
			if object_attrs.get(attr_name, "") in value_list :
				match_value_decl_nodes_list.append(decl_rng_nodes)
			else :
				if len(sub_rng_nodes.get("data", [])) > 0 or len(sub_rng_nodes.get("text", [])) > 0 :
					decl_nodes_list.append(decl_rng_nodes)

		if len(match_value_decl_nodes_list) > 0 :
			decl_nodes_list = match_value_decl_nodes_list

		sorted_nodes = {}
		for decl_type in ["choice", "first_choice", "group", "first_group"] :
			sorted_nodes[decl_type] = manager.get_sorted_decl_nodes(decl_nodes_list, decl_type)

		friend_attrs = []
		opposite_attrs = []
		sub_opposite_attrs = []
		for key in attr_rng_node_dict :
			if key == attr_name :
				continue

			match_value = False
			for attr_rng_node in attr_rng_node_dict[key] :
				decl_rng_nodes = manager.get_decl_rng_nodes(attr_rng_node)
				if decl_rng_nodes.get("choice") == None or \
						decl_rng_nodes.get("choice") not in sorted_nodes["choice"] :
					continue

				value_list = []
				sub_rng_nodes = manager.sorted_sub_rng_nodes_by_node(*attr_rng_node[0])
				for value_node in sub_rng_nodes.get("value", []) :
					value_list.append(value_node[0][1].childNodes[0].data)
				if object_attrs.get(key, "") in value_list :
					if key in friend_attrs :
						friend_attrs.remove(key)
					if key in opposite_attrs :
						opposite_attrs.remove(key)
					if key in sub_opposite_attrs :
						sub_opposite_attrs.remove(key)
					match_value = True

				if len(sorted_nodes["group"]) == 0 :
					opposite_attrs.append(key)
				else :
					if decl_rng_nodes.get("group") not in sorted_nodes["group"] :
						if key not in opposite_attrs :
							opposite_attrs.append(key)
					elif decl_rng_nodes.get("first_choice") in sorted_nodes["first_choice"] and \
							decl_rng_nodes.get("first_group") not in sorted_nodes["first_group"] :
						if key not in sub_opposite_attrs :
							sub_opposite_attrs.append(key)
					else :
						if key not in friend_attrs :
							friend_attrs.append(key)

				if match_value :
					break

		if len(opposite_attrs) == 0 and len(sub_opposite_attrs) == 0 and len(friend_attrs) == 0 :
			return

		if object_attrs.get(attr_name, "") == "" :
			friends_clean = True
			for key in friend_attrs :
				if object_attrs.get(key, "") != "" :
					friends_clean = False
					break
			if friends_clean :
				self.set_sensibility(opposite_attrs, True)

			self.set_sensibility(sub_opposite_attrs, True)
		else :
			self.set_sensibility(opposite_attrs, False)
			self.set_sensibility(sub_opposite_attrs, False)
			self.set_sensibility(friend_attrs, True)

	def dynamic_choice_elem(self) :
		elem_rng_node_dict = self.elem_rng_node_dict
		attr_rng_node_dict = self.attr_rng_node_dict

		object_attrs = self.get_values()

		ref_match_value_decl_nodes_list = []
		ref_decl_nodes_list = []
		for key in object_attrs :
			for attr_rng_node in attr_rng_node_dict.get(key, []) :
				decl_rng_nodes = manager.get_decl_rng_nodes(attr_rng_node)
				value_list = []
				sub_rng_nodes = manager.sorted_sub_rng_nodes_by_node(*attr_rng_node[0])
				for value_node in sub_rng_nodes.get("value", []) :
					value_list.append(value_node[0][1].childNodes[0].data)
				if object_attrs.get(key, "") in value_list :
					ref_match_value_decl_nodes_list.append(decl_rng_nodes)
				elif len(sub_rng_nodes.get("data", [])) > 0 or len(sub_rng_nodes.get("text", [])) > 0 :
					ref_decl_nodes_list.append(decl_rng_nodes)

		if len(ref_match_value_decl_nodes_list) > 0 :
			ref_decl_nodes_list = ref_match_value_decl_nodes_list

		ref_sorted_nodes = {}
		for decl_type in ["choice", "first_choice", "group", "first_group"] :
			ref_sorted_nodes[decl_type] = manager.get_sorted_decl_nodes(ref_decl_nodes_list, decl_type)
			
		elem_node_dict = {}
		for elem_node in self.xml_node.childNodes :
			if elem_node.nodeType != xml.dom.Node.ELEMENT_NODE :
				continue
			elem_type = elem_node.tagName
			if not elem_node_dict.has_key(elem_type) :
				elem_node_dict[elem_type] = []
			elem_node_dict[elem_type].append(elem_node)

		decl_nodes_list = []
		for key in elem_node_dict :
			for elem_rng_node in elem_rng_node_dict.get(key, []):
				if len(elem_node_dict[key]) > 1 and manager.find_decl(elem_rng_node, "oneOrMore") == 0 \
						and manager.find_decl(elem_rng_node, "zeroOrMore") == 0 :
					continue

				decl_rng_nodes = manager.get_decl_rng_nodes(elem_rng_node)
				if decl_rng_nodes.get("choice") == None :
					return

				if decl_rng_nodes.get("choice") in ref_sorted_nodes["choice"] and \
						decl_rng_nodes.get("group") != None and \
						len(ref_sorted_nodes["group"]) > 0 and \
						decl_rng_nodes.get("group") not in ref_sorted_nodes["group"] :
					continue

				decl_nodes_list.append(decl_rng_nodes)

		sorted_nodes = {}
		for decl_type in ["choice", "first_choice", "group", "first_group"] :
			sorted_nodes[decl_type] = manager.get_sorted_decl_nodes(decl_nodes_list, decl_type)

		friend_attrs = []
		opposite_attrs = []
		sub_opposite_attrs = []
		for key in attr_rng_node_dict :
			match_value = False
			for attr_rng_node in attr_rng_node_dict[key] :
				decl_rng_nodes = manager.get_decl_rng_nodes(attr_rng_node)
				if decl_rng_nodes.get("choice") == None or \
						decl_rng_nodes.get("choice") not in sorted_nodes["choice"] :
					friend_attrs.append(key)
					continue

				value_list = []
				sub_rng_nodes = manager.sorted_sub_rng_nodes_by_node(*attr_rng_node[0])
				for value_node in sub_rng_nodes.get("value", []) :
					value_list.append(value_node[0][1].childNodes[0].data)
				if object_attrs.get(key, "") in value_list :
					if key in friend_attrs :
						friend_attrs.remove(key)
					if key in opposite_attrs :
						opposite_attrs.remove(key)
					if key in sub_opposite_attrs :
						sub_opposite_attrs.remove(key)
					match_value = True

				if len(sorted_nodes["group"]) == 0 :
					opposite_attrs.append(key)
				else :
					if decl_rng_nodes.get("group") not in sorted_nodes["group"] :
						if key not in opposite_attrs :
							opposite_attrs.append(key)
					elif decl_rng_nodes.get("first_choice") in sorted_nodes["first_choice"] and \
							decl_rng_nodes.get("first_group") not in sorted_nodes["first_group"] :
						if key not in sub_opposite_attrs :
							sub_opposite_attrs.append(key)
					else :
						if key not in friend_attrs :
							friend_attrs.append(key)

				if match_value :
					break

		if len(opposite_attrs) == 0 and len(sub_opposite_attrs) == 0 and len(friend_attrs) == 0 :
			return

		self.set_sensibility(opposite_attrs, False)
		self.set_sensibility(sub_opposite_attrs, False)
		self.set_sensibility(friend_attrs, True)

	def set_sensibility(self, keys, sensibility) :
		widgets = self.widgets
		for widget_type in widgets :
			if type(widgets[widget_type]) != dict :
				continue
			for key in widgets[widget_type] :
				if key in keys :
					widgets[widget_type][key].set_sensitive(sensibility)

	def set_id_widget(self, id) :
		widgets = self.widgets
		if self.is_newobj :
			if widgets.get("combo_entries", {}).has_key("id") :
				widgets["combo_entries"]["id"].child.set_text(id)
		else :
			if widgets.get("value_labels", {}).has_key("id") :
				widgets["value_labels"]["id"].set_text(id)

	def hide_id_widget(self) :
		widgets = self.widgets
		if widgets.get("name_labels", {}).has_key("id") :
			widgets["name_labels"]["id"].hide_all()
		if self.is_newobj :
			if widgets.get("combo_entries", {}).has_key("id") :
				widgets["combo_entries"]["id"].hide_all()
		else :
			if widgets.get("value_labels", {}).has_key("id") :
				widgets["value_labels"]["id"].hide_all()

	def dynamic_set_id_auto(self, widget) :
		key_attrs = ["name", "attribute"]
		widgets = self.widgets
		if not widgets.has_key("combo_entries") :
			return
		if widget not in [widgets["combo_entries"].get(attr) for attr in key_attrs] :
			return
				
		object_attrs = self.get_values()
		for attr in key_attrs :
			name = object_attrs.get(attr, "")
			if name != "" :
				break

		if name == "" :
			name = self.obj_type
			
		new_id = manager.auto_unique_id(self.xml_node, name)
		self.set_id_widget(new_id)

class Primitive(ObjectAttrs) :
	def dynamic_fill(self, widget) :
		widgets = self.widgets

		primitive = self.get_values()
		primitive_class = primitive.get("class", "")
		if primitive_class == "" :
			return

		if widgets.has_key("combos") and widgets["combos"].has_key("class") \
				and widget == widgets["combos"]["class"] :
			ra_list = manager.get_rsc_types(primitive_class)
			self.fill_provider(primitive, ra_list)
			self.fill_type(primitive, ra_list)

		elif widgets.has_key("combo_entries") and widgets["combo_entries"].has_key("provider") \
				and widget == widgets["combo_entries"]["provider"] :
			ra_list = manager.get_rsc_types(primitive_class)
			self.fill_type(primitive, ra_list)

	def fill_provider(self, primitive, ra_list = None) :
		widgets = self.widgets
		primitive_class = primitive.get("class", "")

		provider_list = []
		if primitive_class == "ocf" and ra_list != None :
			for ra in ra_list :
				providers = manager.get_rsc_providers(primitive_class, ra)
				for provider in providers :
					if provider_list.count(provider) == 0 :
						provider_list.append(provider)

		providers_store = [[provider, ""] for provider in provider_list]
		if widgets.has_key("combo_entries") and widgets["combo_entries"].has_key("provider") :
			self.combobox_store_append(widgets["combo_entries"]["provider"], providers_store)
		#	if provider_list != None and len(provider_list) > 0 :
		#		widgets["combo_entries"]["provider"].child.set_text(provider_list[0])

	def fill_type(self, primitive, ra_list = None) :
		widgets = self.widgets
		primitive_class = primitive.get("class", "")
		primitive_provider = primitive.get("provider", "")
		if ra_list != None :
			ra_list.sort()
			if primitive_class != "ocf" or primitive_provider == "" :
				type_store = [[ra, ""] for ra in ra_list]
			else :
				type_store = []
				for ra in ra_list :
					provider_list = manager.get_rsc_providers(primitive_class, ra)
					if provider_list != None and primitive_provider in provider_list :
						type_store.append([ra, ""])

			if widgets.has_key("combo_entries") and widgets["combo_entries"].has_key("type") :
				self.combobox_store_append(widgets["combo_entries"]["type"], type_store)

	def dynamic_desc(self, widget) :
		widgets = self.widgets
		desc = None
		if widgets.has_key("combos") and widgets["combos"].has_key("class") \
				and widget == widgets["combos"]["class"] :
			desc = self.get_meta_desc()

		if widgets.has_key("combo_entries") and widgets["combo_entries"].has_key("type") \
				and widget == widgets["combo_entries"]["type"] :
			desc = self.get_meta_desc()

		if widgets.has_key("combo_entries") and widgets["combo_entries"].has_key("provider") \
				and widget == widgets["combo_entries"]["provider"] :
			desc = self.get_meta_desc()

                if widgets.has_key("combo_entries") and widgets["combo_entries"].has_key("template") \
                                and widget == widgets["combo_entries"]["template"] :
                        desc = self.get_meta_desc()

		return desc

	def get_meta_desc(self) :
		primitive = self.get_values()

		primitive_template = primitive.get("template")

                title = ""
                if not primitive_template :
                        primitive_class = primitive.get("class", "")
                        primitive_type = primitive.get("type", "")
                        primitive_provider = primitive.get("provider", "pacemaker")
                else :
                        template_node = manager.get_template(primitive_template)
                        if template_node == None :
                                return [""]

                        primitive_attrs = manager.get_rsc_attrs(template_node, ["class", "type", "provider"])
                        primitive_class = str(primitive_attrs.get("class", ""))
                        primitive_type = str(primitive_attrs.get("type", ""))
                        primitive_provider = str(primitive_attrs.get("provider", "pacemaker"))

                        title = "%s:%s:%s\n\n"%(primitive_class, primitive_provider, primitive_type)

		meta = manager.get_rsc_meta(primitive_class, primitive_type, primitive_provider) 
		if meta == None :
			return [""]

		longdesc = meta.longdesc
		if longdesc == None :
			longdesc = ""
		else :
			longdesc = longdesc.replace(_(".  "), _(".\n"))

		shortdesc = meta.shortdesc
		if shortdesc == None :
			shortdesc = ""

		if len(longdesc) == 0 :
			desc = [title + shortdesc]
		elif longdesc.find(shortdesc) > -1 :
			desc = [title + longdesc]
		else :
			if shortdesc.endswith(_(".")) :
				desc = [title + shortdesc + "\n" + longdesc]
			else :
				desc = [title + shortdesc + _(".") + "\n" + longdesc]
		return desc

	def verify_values(self) :
		if not ObjectAttrs.verify_values(self) :
			return False

		primitive = self.get_values()
		if self.is_newobj and manager.rsc_exists(primitive.get("id", "")):
			msgbox(top_window, _("the ID already exists"))
			return False

		if primitive.get("template", "") == "" and primitive.get("class", "") == "" :
			msgbox(top_window, _("\"%s\" or \"%s\" is required")%(_("Class"), _("Template")))
			return False

		if primitive.get("class", "") == "ocf" and primitive.get("provider", "") == "" :
			msgbox(top_window, _("\"%s\" is required")%_("Provider") + " " +
					_("for an OCF primitive"))
			return False

		return True

class MetaAttrsNV(ObjectAttrs) :
	def __init__(self, xml_node, is_newobj = False, change_call_back = None) :
		common_options = [
		("priority", [], 
		 _("If not all resources can be active, the cluster will stop lower priority resources in order to keep higher priority ones active.")), 
		("target-role", [["Started", _("[ default ]")], ["Stopped", ""]],
		 _("What state should the cluster attempt to keep this resource in?")),
		("is-managed", [["true", _("[ default ]")], ["false", ""]],
		 _("Is the cluster allowed to start and stop the resource?"))
		]

		primitive_options = [
		("resource-stickiness", [],
		 _("How much does the resource prefer to stay where it is? Defaults to the value of \"default-resource-stickiness\"")),
		("migration-threshold", [],
		 _("How many failures should occur for this resource on a node before making the node ineligible to host this resource. Default: \"none\"")),
		("multiple-active", [["stop_start", _("[ default ]")], ["stop_only", ""], ["block", _("(mark the resource as unmanaged)")]],
		 _("What should the cluster do if it ever finds the resource active on more than one node.")),
		("failure-timeout", [],
		 _("How many seconds to wait before acting as if the failure had not occurred (and potentially allowing the resource back to the node on which it failed. Default: \"never\"")),
                ("allow-migrate", [["false", _("[ default ]")], ["true", ""]],
                 _("Allow resource migration for resources which support migrate_to/migrate_from actions"))
		]

		clone_basic_options = [
		("clone-max", [],
		 _("How many copies of the resource to start. Defaults to the number of nodes in the cluster.")),
		("clone-node-max", [["1", _("[ default ]")]],
		 _("How many copies of the resource can be started on a single node.")),
		]
		clone_other_options = [
		("notify", [["false", _("[ default ]")], ["true", ""]],
		 _("When stopping or starting a copy of the clone, tell all the other copies beforehand and when the action was successful.")),
		("globally-unique", [["false", _("[ default ]")], ["true", ""]],
		 _("Does each copy of the clone perform a different function?")),
		("ordered", [["false", _("[ default ]")], ["true", ""]],
		 _("Should the copies be started in series (instead of in parallel)")),
		("interleave", [["false", _("[ default ]")], ["true", ""]],
		 _("Changes the behavior of ordering constraints (between clones/masters) so that instances can start/stop as soon as their peer instance has (rather than waiting for every instance of the other clone has)."))
		]

		master_basic_options = [
		("master-max", [["1", _("[ default ]")]],
		 _("How many copies of the resource can be promoted to master status.")),
		("master-node-max", [["1", _("[ default ]")]],
		 _("How many copies of the resource can be promoted to master status on a single node."))
		]

		#neoshineha add
		master_other_options = [
                ("notify", [["1", _("[ default ]")], ["true", ""]],
                 _("When stopping or starting a copy of the clone, tell all the other copies beforehand and when the action was successful.")),
                ("globally-unique", [["false", _("[ default ]")], ["true", ""]],
                 _("Does each copy of the clone perform a different function?")),
                ("ordered", [["false", _("[ default ]")], ["true", ""]],
                 _("Should the copies be started in series (instead of in parallel)")),
                ("interleave", [["false", _("[ default ]")], ["true", ""]],
                 _("Changes the behavior of ordering constraints (between clones/masters) so that instances can start/stop as soon as their peer instance has (rather than waiting for every instance of the other clone has)."))
                ]
		#neoshineha

		self.meta_attributes_options = {
		"primitive": common_options + primitive_options,
		"group": common_options,
		"clone": common_options + clone_basic_options + clone_other_options,
		"master": common_options + clone_basic_options + master_basic_options + master_other_options,
		"rsc_defaults": common_options + primitive_options,
		}

		if validate_type == "dtd" :
			self.target_node = xml_node.parentNode.parentNode.parentNode
			self.target_type = self.target_node.tagName
			self.target_dtd_elem = manager.get_dtd_elem(self.target_type)
			self.target_attrlist = self.target_dtd_elem.get_attr_list()
			self.auto_fill = self.auto_fill_dtd
			self.dynamic_fill = self.dynamic_fill_dtd
		else :
			self.target_node = xml_node.parentNode.parentNode
			self.target_type = self.target_node.tagName
			self.auto_fill = self.auto_fill_rng
			self.dynamic_fill = self.dynamic_fill_rng
			self.dynamic_desc = self.dynamic_desc_rng
			
		ObjectAttrs.__init__(self, xml_node, is_newobj, change_call_back)

	def auto_fill_rng(self) :
		widgets = self.widgets
		name_store = [[option[0], ""] for option in self.meta_attributes_options.get(self.target_type, [])]
		if widgets.get("combo_entries", {}).has_key("name") :
			self.combobox_store_append(widgets["combo_entries"]["name"], name_store)

	def dynamic_fill_rng(self, widget) :
		widgets = self.widgets
		if widgets.get("combo_entries", {}).has_key("name") \
				and widget == widgets["combo_entries"]["name"] :
			value_store = []
			nvpair = self.get_values()
			if nvpair.has_key("name") :
				options = self.meta_attributes_options.get(self.target_type, [])
				for i in range(len(options)) :
					if options[i][0] == nvpair["name"] :
						value_store = options[i][1]
						break

			if widgets.get("combo_entries", {}).has_key("value") :
				self.combobox_store_append(widgets["combo_entries"]["value"], value_store)

	def dynamic_desc_rng(self, widget) :
		widgets = self.widgets
		if widgets.get("combo_entries", {}).get("name") != widget :
			return None

		desc = [""]
		nvpair =  self.get_values()
		if nvpair.has_key("name") :
			options = self.meta_attributes_options.get(self.target_type, [])
			for i in range(len(options)) :
				if options[i][0] == nvpair["name"] :
					desc = [options[i][2]]
					break

		return desc

	def auto_fill_dtd(self) :
		widgets = self.widgets
		attr_store = []

		if self.target_type in ["primitive", "template", "group", "clone", "master_slave"] :
			attr_store.append(["target_role", ""])

		for attr_name in self.target_attrlist :
			attr = self.target_dtd_elem.get_attr(attr_name)
			if attr.get_decl() !=  "#REQUIRED" :
				attr_store.append([attr_name, ""])

		if self.target_type in ["clone", "master_slave"] :
			attr_store.extend([attr_name, ""] for attr_name in ["clone_max", "clone_node_max"])

		if self.target_type == "master_slave" :
			attr_store.extend([attr_name, ""] for attr_name in ["master_max", "master_node_max"])


		if widgets.has_key("combo_entries") and widgets["combo_entries"].has_key("name") :
			self.combobox_store_append(widgets["combo_entries"]["name"], attr_store)

	def dynamic_fill_dtd(self, widget) :
		widgets = self.widgets
		options_dict = {"target_role": ["started", "stopped", "default"]}

		if widgets.has_key("combo_entries") and widgets["combo_entries"].has_key("name") \
				and widget == widgets["combo_entries"]["name"] :
			metaattr = self.get_values()
			attr_name = metaattr.get("name", None)
			if attr_name == None :
				return
			value_store = []
			if attr_name in self.target_attrlist :
				attr = self.target_dtd_elem.get_attr(attr_name)
				attr_type = attr.get_type()
				attr_default = attr.get_default()
				if  type(attr_type) == list :
					if attr_type.count("true") > 0 and attr_type.count("false") > 0 :
						options = ("true", "false")
					else :
						options = attr_type
					for option in options :
						if attr_default != None and option == attr_default :
							value_store.append([attr_default, "[ " + _("default") + " ]"])
						else :
							value_store.append([option, ""])
				elif attr_default != None :
					value_store.append([attr_default, "["+_("default")+"]"])
			elif attr_name in options_dict.keys() :
				value_store.extend([attr_value, ""] for attr_value in options_dict[attr_name])
				if self.target_node.parentNode.tagName == "clone" :
					value_store.extend([attr_value, ""] for attr_value in ["master", "slave"])

			if widgets.has_key("combo_entries") and widgets["combo_entries"].has_key("value") :
				self.combobox_store_append(widgets["combo_entries"]["value"], value_store)

class MetaNV(ObjectAttrs) :
	meta = None
	def auto_fill(self) :
		widgets = self.widgets
		meta = self.meta
		if meta != None :
			instattr_store = []
			for param in meta.parameters :
				param_attr = ""
				if param.get("required", None) == "1" :
					param_attr =  param_attr + _("required")
				if param.get("unique", None) == "1" :
					if param_attr != "" :
						param_attr = param_attr + _(", ")
					param_attr = param_attr + _("unique")
				if param_attr != "" :
					param_attr = "[ "+ param_attr + " ]"
				instattr_store.append([param["name"], param_attr])
					
			if widgets.has_key("combo_entries") and widgets["combo_entries"].has_key("name") :
				self.combobox_store_append(widgets["combo_entries"]["name"], instattr_store)

	def dynamic_fill(self, widget) :
		widgets = self.widgets
		meta = self.meta
		if widgets.has_key("combo_entries") and widgets["combo_entries"].has_key("name") \
				and widget == widgets["combo_entries"]["name"] \
				and meta != None :
			instattr = self.get_values()
			value_store = []
			if instattr.has_key("name") :
				for param in meta.parameters :
					if instattr["name"] == param["name"] :
						param_type = param["content"].get("type")
						options = []
						default_value = param["content"]["default"]
						if param_type == "boolean" :
                                                        boolean_values = [["true", "false"], ["yes", "no"], ["1", "0"]]
                                                        if default_value :
                                                                options = None
                                                                for value_pair in boolean_values :
                                                                        if default_value in value_pair :
                                                                                options = value_pair
                                                                                break
                                                                if options == None :
                                                                        options = [default_value]
                                                        else :
                                                                options = boolean_values[0]
						elif param_type == "enum" and param["content"].has_key("values"):
							options =  param["content"]["values"]
						elif default_value != None :
							options = [default_value]

						for option in options :
							if default_value != None and option == default_value :
								value_store.insert(0, [option, "[ "+ _("default") + " ]"])
							else :
								value_store.append([option, ""])
						break
			if widgets.has_key("combo_entries") and widgets["combo_entries"].has_key("value") :
				self.combobox_store_append(widgets["combo_entries"]["value"], value_store)

	def dynamic_desc(self, widget) :
		widgets = self.widgets
		meta = self.meta
		if meta == None or not widgets.has_key("combo_entries") \
				or widget != widgets["combo_entries"].get("name") :
			return None

		desc = [""]
		instattr = self.get_values()
		if instattr.has_key("name") :
			for param in meta.parameters :
				if instattr["name"] == param["name"] :		
					longdesc = param.get("longdesc", "").replace(_(".  "), _(".\n"))
					shortdesc = param.get("shortdesc", "")

					if len(longdesc) == 0 :
						desc = [shortdesc]
					elif longdesc.find(shortdesc) > -1 :
						desc = [longdesc]
					else :
						if shortdesc.endswith(_(".")) :
							desc = [shortdesc + "\n" + longdesc]
						else :
							desc = [shortdesc + _(".") + "\n" + longdesc]
					break
		return desc

class CRMConfNV(MetaNV) :
	meta = None
	def __init__(self, xml_node, is_newobj = False, change_call_back = None) :
		self.meta = manager.get_crm_metadata("pengine")
		crmd_meta = manager.get_crm_metadata("crmd")
		if self.meta != None :
			if crmd_meta != None:
				self.meta.parameters.extend(crmd_meta.parameters)
				params = {}
				for param in self.meta.parameters :
					params[param["name"]] = param

				param_names = params.keys()
				param_names.sort()
				self.meta.parameters = []
				for param_name in param_names :
					self.meta.parameters.append(params[param_name]) 
		else :
			self.meta = crmd_meta
		MetaNV.__init__(self, xml_node, is_newobj, change_call_back)

class PrimInstAttrsNV(MetaNV) :
	meta = None
	def __init__(self, xml_node, is_newobj = False, change_call_back = None) :
		if validate_type == "dtd" :
			primitive_node = xml_node.parentNode.parentNode.parentNode
		else :
			primitive_node = xml_node.parentNode.parentNode

                primitive_attrs = manager.get_rsc_attrs(primitive_node, ["class", "type", "provider"])
                primitive_class = str(primitive_attrs.get("class", ""))
                primitive_type = str(primitive_attrs.get("type", ""))
                primitive_provider = str(primitive_attrs.get("provider", ""))

		self.meta = manager.get_rsc_meta(primitive_class, primitive_type, primitive_provider)
		MetaNV.__init__(self, xml_node, is_newobj, change_call_back)

class OPInstAttrsNV(ObjectAttrs) :
	def auto_fill(self) :
		widgets = self.widgets
		name_store = [["OCF_CHECK_LEVEL", ""]]
		if widgets.get("combo_entries", {}).has_key("name") :
			self.combobox_store_append(widgets["combo_entries"]["name"], name_store)

class UtilizationNV(ObjectAttrs) :
        def auto_fill(self) :
                widgets = self.widgets
                utilization_names = ["cpu", "memory"]
                name_store = [[name, ""] for name in utilization_names]
                if widgets.get("combo_entries", {}).has_key("name") :
                        self.combobox_store_append(widgets["combo_entries"]["name"], name_store)

class InstAttrsNV(ObjectAttrs) :
	def __init__(self, xml_node, is_newobj = False, change_call_back = None) :
		self.attributes_options = {
		"node": [
		("standby", [["false", "[ default ]"], ["true", ""]]),
		("cpu_mips", [])
		]
		}

		if validate_type == "dtd" :
			self.target_node = xml_node.parentNode.parentNode.parentNode
			self.target_type = self.target_node.tagName
		else :
			self.target_node = xml_node.parentNode.parentNode
			self.target_type = self.target_node.tagName

		ObjectAttrs.__init__(self, xml_node, is_newobj, change_call_back)

	def auto_fill(self) :
		widgets = self.widgets
		name_store = [[option[0], ""] for option in self.attributes_options.get(self.target_type, [])]
		if widgets.get("combo_entries", {}).has_key("name") :
			self.combobox_store_append(widgets["combo_entries"]["name"], name_store)

	def dynamic_fill(self, widget) :
		widgets = self.widgets
		if widgets.get("combo_entries", {}).has_key("name") \
				and widget == widgets["combo_entries"]["name"] :
			value_store = []
			nvpair = self.get_values()
			if nvpair.has_key("name") :
				options = self.attributes_options.get(self.target_type, [])
				for i in range(len(options)) :
					if options[i][0] == nvpair["name"] :
						value_store = options[i][1]
						break

			if widgets.get("combo_entries", {}).has_key("value") :
				self.combobox_store_append(widgets["combo_entries"]["value"], value_store)

class OPDefaultsNV(ObjectAttrs) :
	def __init__(self, xml_node, is_newobj = False, change_call_back = None) :
		self.op_attr_rng_nodes = {}
		self.op_attr_list = []
		sorted_rng_nodes = manager.sorted_sub_rng_nodes_by_name("op")
		if sorted_rng_nodes != None :
			attr_rng_nodes = sorted_rng_nodes.get("attribute", [])
			for rng_node in attr_rng_nodes :
				name = rng_node[0][1].getAttribute("name")
				if name in ["id", "name", "description"] :
					continue
				if not self.op_attr_rng_nodes.has_key(name) :
					self.op_attr_rng_nodes[name] = []
					self.op_attr_list.append(name)
				self.op_attr_rng_nodes[name].append(rng_node)

		ObjectAttrs.__init__(self, xml_node, is_newobj, change_call_back)

	def auto_fill(self) :
		widgets = self.widgets
		name_store = [[name, ""] for name in self.op_attr_list]
		if widgets.get("combo_entries", {}).has_key("name") :
			self.combobox_store_append(widgets["combo_entries"]["name"], name_store)

	def dynamic_fill(self, widget) :
		widgets = self.widgets
		if widgets.get("combo_entries", {}).has_key("name") \
				and widget == widgets["combo_entries"]["name"] :
			nvpair = self.get_values()
			if nvpair.has_key("name") :
				value_store = []
				for attr_rng_node in self.op_attr_rng_nodes.get(nvpair["name"], []):
					sub_rng_nodes = manager.sorted_sub_rng_nodes_by_node(*attr_rng_node[0])
					if len(sub_rng_nodes.get("value",[])) > 0 :
						for value_node in sub_rng_nodes["value"] :
							value_store.append([value_node[0][1].childNodes[0].data, ""])
					for sub_rng_node in sub_rng_nodes.get("data", []) :
						if sub_rng_nodes["data"][0][0][1].getAttribute("type") == "boolean" :
							for option in ("true", "false") :
								value_store.append([option, ""])

				if widgets.get("combo_entries", {}).has_key("value") :
					self.combobox_store_append(widgets["combo_entries"]["value"], value_store)

class Expression(ObjectAttrs) :
	def __init__(self, xml_node, is_newobj = False, change_call_back = None) :
		ObjectAttrs.__init__(self, xml_node, is_newobj, change_call_back)

	def auto_fill(self) :
		widgets = self.widgets
		attr_names = ["#uname","#id", "#is_dc"]
		attr_store = [[attr_name, ""] for attr_name in attr_names]
		
		if widgets.has_key("combo_entries") and widgets["combo_entries"].has_key("attribute") :
			self.combobox_store_append(widgets["combo_entries"]["attribute"], attr_store)

	def dynamic_fill(self, widget) :
		widgets = self.widgets
		if widgets.has_key("combo_entries") and widgets["combo_entries"].has_key("attribute") \
				and widget == widgets["combo_entries"]["attribute"] :
			expr = self.get_values()
			value_store = []
			if expr.has_key("attribute") :
				if expr["attribute"] == "#uname" :
					value_store = [[node, ""] for node in manager.get_normal_nodes()]
				elif expr["attribute"] == "#is_dc" :
					value_store = [[boolean_val, ""] for boolean_val in ["true", "false"]]

			if widgets.has_key("combo_entries") and widgets["combo_entries"].has_key("value") :
				self.combobox_store_append(widgets["combo_entries"]["value"], value_store)

class OP(ObjectAttrs) :
	def __init__(self, xml_node, is_newobj = False, change_call_back = None) :
		if mode_level == 0 :
			self.dynamic_layout = self.dynamic_layout_simple
		primitive_node = xml_node.parentNode.parentNode
		primitive_attrs = manager.get_rsc_attrs(primitive_node, ["class", "type", "provider"])
                primitive_class = str(primitive_attrs.get("class", ""))
                primitive_type = str(primitive_attrs.get("type", ""))
                primitive_provider = str(primitive_attrs.get("provider", ""))
		meta = manager.get_rsc_meta(primitive_class, primitive_type, primitive_provider)
		self.meta = meta
		ObjectAttrs.__init__(self, xml_node, is_newobj, change_call_back)
		self.dynamic_fill = self.dynamic_fill_later

	def auto_fill(self) :
		widgets = self.widgets
		meta = self.meta
		actions = ["start", "stop", "reload", "monitor", "status", "migrate_from", "migrate_to", "promote", "demote"]
		op_names = []
		if meta != None :
			for action in meta.actions :
				if action["name"] not in op_names :
					op_names.append(action["name"])
		else :
			op_names = actions
		op_name_store = [[op_name, ""] for op_name in op_names]

		if widgets.has_key("combo_entries") and widgets["combo_entries"].has_key("name") :
			self.combobox_store_append(widgets["combo_entries"]["name"], op_name_store)

	def dynamic_fill_later(self, widget) :
		widgets = self.widgets
		meta = self.meta
		if meta == None or not widgets.has_key("combo_entries") :
			return
		elif widget != widgets["combo_entries"].get("name") :
			if not widgets.has_key("combos") :
				return
			elif widget != widgets["combos"].get("role") :
				return

		op = self.get_values()
		if op.has_key("name") :
			if validate_type == "dtd" :
				default_role = manager.get_dtd_elem("op").get_attr("role").get_default()
			else :
				default_role = None

			for action in meta.actions :
				if action["name"] == op["name"] :
					if action.get("role") == op.get("role") \
							or ( action.get("role") == None and op.get("role") == default_role ) \
							or ( action.get("role") == default_role and op.get("role") == None) :
						for attr_name in widgets["combo_entries"].keys() :
							if attr_name != "id" and attr_name != "name" and attr_name != "role":
								attr_store = []
								if attr_name == "start_delay" and action.has_key("start-delay") :
									action["start_delay"] = action["start-delay"]
								if action.has_key(attr_name) :
									attr_store.append([action[attr_name], ""])
								self.combobox_store_append(widgets["combo_entries"][attr_name], attr_store)
								widgets["combo_entries"][attr_name].child.set_text(action.get(attr_name, ""))
						break

			if op["name"] != "monitor" and widgets["combo_entries"].has_key("interval") \
					and widgets["combo_entries"]["interval"].get_property("sensitive") \
					and widgets["combo_entries"]["interval"].child.get_text() == "" :
				is_required = False
				for child_widget in self.required_vbox.get_children() :
					if type(child_widget) == gtk.HBox \
							and widgets["combo_entries"]["interval"] in child_widget.get_children() :
						is_required = True
						break
				if is_required or mode_level == 0 :
					widgets["combo_entries"]["interval"].child.set_text("0")

		else :
			for attr_name in widgets["combo_entries"].keys() :
				if attr_name != "name" :
					self.combobox_store_append(widgets["combo_entries"][attr_name], [])
					widgets["combo_entries"][attr_name].child.set_text("")

	def dynamic_layout_simple(self, widget) :
		widgets = self.widgets
		required_vbox = self.required_vbox
		optional_vbox = self.optional_vbox

		if not widgets.has_key("combo_entries") :
			return
		elif widget != widgets["combo_entries"].get("name") :
			return

		op = self.get_values()
		if op.get("name", "") in ["", "monitor"] :
			required_attrs = ["id", "name", "interval", "timeout"]
		else :
			required_attrs = ["id", "name", "timeout"]

		for vbox in [required_vbox, optional_vbox] :
			for child in vbox.get_children() :
				vbox.remove(child)

		for attr_name in self.attr_list :
			if attr_name in required_attrs :
				required_vbox.pack_start(self.hboxes[attr_name], False, padding=2)
			else :
				optional_vbox.pack_start(self.hboxes[attr_name], False, padding=2)

		required_vbox.show_all()
		optional_vbox.show_all()
		if mode_level == 0 :
			self.hide_id_widget()
		top_window.set_focus(widgets["combo_entries"]["name"].child)

	def verify_values(self) :
		if not ObjectAttrs.verify_values(self) :
			return False

		time_attrs = ["interval", "timeout"]
		if validate_type == "dtd" :
			time_attrs.append("start_delay")
		else :
			time_attrs.append("start-delay")

		op = self.get_values()
		for time_attr in time_attrs :
			if op.get(time_attr, "") != "" :
				(is_valid, error_msg) = is_valid_time(op[time_attr])
				if not is_valid :
					msgbox(top_window, _("Invalid \"%s\"")%(_(name_cap(time_attr))) + _(":") + "\n" +
							error_msg)
					return False
		return True

	def dynamic_set_id(self, widget) :
		widgets = self.widgets
		if mode_level != 0 or not widgets.has_key("combo_entries") :
			return
		if widget not in [widgets["combo_entries"].get("name"), widgets["combo_entries"].get("interval")] :
			if not widgets.has_key("combos") :
				return
			if widget != widgets["combos"].get("role") :
				return
				
		op = self.get_values()
		primitive_id = self.xml_node.parentNode.parentNode.getAttribute("id")
		op_id = primitive_id + "-op"
		name = op.get("name", "")
		if name != "" :
			op_id += "-" + name
		role = op.get("role", "")
		if role != "" :
			op_id += "-" + role
		interval = op.get("interval", "")
		if interval != "" :
			op_id += "-" + interval
			
		new_id = manager.get_unique_id(op_id, self.xml_node)
		self.set_id_widget(new_id)

class RscOrder(ObjectAttrs) :
	def __init__(self, xml_node, is_newobj = False, change_call_back = None) :
		if validate_type == "dtd" :
			self.dynamic_fill = self.dynamic_fill_dtd
			self.dynamic_desc = self.dynamic_desc_dtd
		else :
			self.dynamic_desc = self.dynamic_desc_rng
		ObjectAttrs.__init__(self, xml_node, is_newobj, change_call_back)

	def dynamic_fill_dtd(self, widget) :
		widgets = self.widgets
		if widgets.has_key("combo_entries") and widgets["combo_entries"].has_key("from") \
				and widget == widgets["combo_entries"]["from"] :
			key_pair = ["from", "action"]
		elif widgets.has_key("combo_entries") and widgets["combo_entries"].has_key("to") \
				and widget == widgets["combo_entries"]["to"] :
			key_pair = ["to", "to_action"]
		else :
			return

		object = self.get_values()
		actions_list = ["start", "stop", "reload", "monitor", "status", "migrate_from", "migrate_to", "promote", "demote"]

		actions = actions_list
		if object.has_key(key_pair[0]) :
			rsc_info = manager.get_rsc_info(object[key_pair[0]])
			if rsc_info != None :
				meta = manager.get_rsc_meta(*rsc_info)
				if meta != None :
					actions = []
					for f in meta.actions :
						if not f["name"] in actions : 
							actions.append(f["name"])

		action_store = [[action, ""] for action in actions]

		if widgets.has_key("combo_entries") and widgets["combo_entries"].has_key(key_pair[1]) :
			self.combobox_store_append(widgets["combo_entries"][key_pair[1]], action_store)

	def dynamic_desc_dtd(self, widget) :
		dtd_elem = self.dtd_elem
		order = self.get_values()
		for attr_name in dtd_elem.get_attr_list() :
			attr = dtd_elem.get_attr(attr_name)
			if not order.has_key(attr_name) :
				if attr_name != "id" and attr.get_decl() == "#REQUIRED" :
					return [_("* Specify dependencies between the actions on two resources"), 
						_("* Please set the required attributes"), "", ""]
				order[attr_name] = attr.get_default()
			if order[attr_name] == None :
				order[attr_name] = ""
		desc = []
		desc.append(_("* %s %s %s %s %s")
				%(order["action"].capitalize(), order["from"], order["type"], order["to_action"], order["to"]))

		if order["score"] == "INFINITY" or order["score"] == "infinity":
			if order["type"] == "before" :
				desc.append(_("* If cannot %s %s, do not %s %s")
						%(order["action"], order["from"], order["to_action"], order["to"]))
			else :
				desc.append(_("* If cannot %s %s, do not %s %s")
						%(order["to_action"], order["to"], order["action"], order["from"]))
		else :
			desc.append("")

		action = self.invert_action(order["action"])
		to_action = self.invert_action(order["to_action"])
		if order["symmetrical"] == "true" and action != None and to_action != None :
			desc.append(_("* %s %s %s %s %s")
					%(to_action.capitalize(), order["to"], order["type"], action, order["from"]))
			if order["score"] == "INFINITY" or order["score"] == "infinity":
				if order["type"] == "before" :
					desc.append(_("* If cannot %s %s, do not %s %s")
							%(to_action, order["to"], action, order["from"]))
				else :
					desc.append(_("* If cannot %s %s, do not %s %s")
							%(action, order["from"], to_action, order["to"]))
			else:
				desc.append("")
		else :
			desc.append("")
			desc.append("")

		return desc

	def invert_action(self, action) :
		if action == "start" :
			return "stop"
		elif action == "stop" :
			return "start"
		elif action == "promote" :
			return "demote"
		elif action == "demote" :
			return "promote"
		elif action == "promoted" :
			return "demoted"
		elif action == "demoted" :
			return "promoted"
		if action == "started" :
			return "stopped"
		elif action == "stopped" :
			return "started"
		else :
			return None

	def dynamic_desc_rng(self, widget) :
		attr_list = self.attr_list
		order = self.get_values()
		for attr_name in self.attr_list :
			if attr_name in ["first", "then"] and not order.has_key(attr_name) :
				return [_("* Specify the order of actions on resources"), 
						_("* Please set the required attributes or add resource sets"), "", ""]
			if order.get(attr_name) == None :
				if attr_name in ["first-action", "then-action"] :
					order[attr_name] = "start"
				elif attr_name == "score" :
					order[attr_name] = "INFINITY"
				elif attr_name == "symmetrical" :
					order[attr_name] = "true"
				else :
					order[attr_name] = ""
		desc = []
		desc.append(_("* %s %s before %s %s")
				%(order["first-action"].capitalize(), order["first"], order["then-action"], order["then"]))

		score = self.get_score(order["score"])

		if score > 0 :
			desc.append(_("* If cannot %s %s, do not %s %s")
					%(order["first-action"], order["first"], order["then-action"], order["then"]))
		else :
			desc.append("")

		first_action = self.invert_action(order["first-action"])
		then_action = self.invert_action(order["then-action"])
		if order["symmetrical"] == "true" and first_action != None and then_action != None :
			desc.append(_("* %s %s before %s %s")
					%(then_action.capitalize(), order["then"], first_action, order["first"]))
			if score > 0 :
				desc.append(_("* If cannot %s %s, do not %s %s")
						%(then_action, order["then"], first_action, order["first"]))
			else:
				desc.append("")
		else :
			desc.append("")
			desc.append("")

		return desc

class RscColocation(ObjectAttrs) :
	def __init__(self, xml_node, is_newobj = False, change_call_back = None) :
		if validate_type == "dtd" :
			self.dynamic_desc = self.dynamic_desc_dtd
		else :
			self.dynamic_desc = self.dynamic_desc_rng
		ObjectAttrs.__init__(self, xml_node, is_newobj, change_call_back)

	def dynamic_desc_dtd(self, widget) :
		dtd_elem = self.dtd_elem
		colocation = self.get_values()
		for attr_name in dtd_elem.get_attr_list() :
			attr = dtd_elem.get_attr(attr_name)
			if not colocation.has_key(attr_name) :
				if attr_name != "id" and attr.get_decl() == "#REQUIRED" :
					return [_("* Specify where a resource should run relative to another resource"),
						_("* Please set the required attributes"), "", ""]
				colocation[attr_name] = attr.get_default()
			if colocation[attr_name] == None :
				colocation[attr_name] = ""
		desc = []

		if colocation["score"] == "INFINITY" or colocation["score"] == "infinity" :
			desc.append(_("* Make %s %s on the same node as %s %s  ( %s according to %s )")
					%(colocation["from"], colocation["from_role"], colocation["to"], colocation["to_role"],
					colocation["from"], colocation["to"]))
			desc.append(_("* If %s cannot be %s on any node, then %s won't be %s anywhere")
					%(colocation["to"], colocation["to_role"], colocation["from"], colocation["from_role"]))
			if colocation["symmetrical"] == "false" :
				desc.append(_("* If %s cannot be %s on any node, %s won't be affected")
						%(colocation["from"], colocation["from_role"], colocation["to"]))
				desc.append("")
			else : 
				desc.append(_("* Make %s %s on the same node as %s %s  ( %s according to %s )")
						%(colocation["to"], colocation["to_role"], colocation["from"], colocation["from_role"],
						colocation["to"], colocation["from"]))
				desc.append(_("* If %s cannot be %s on any node, then %s won't be %s anywhere")
						%(colocation["from"], colocation["from_role"], colocation["to"], colocation["to_role"]))
		elif colocation["score"] == "-INFINITY" or colocation["score"] == "-infinity" :
			desc.append(_("* Prevent %s from being %s on the same node as %s %s  ( %s according to %s )")
					%(colocation["from"], colocation["from_role"], colocation["to"], colocation["to_role"],
					colocation["from"], colocation["to"]))
			desc.append(_("* If %s is %s on the only (or every) available node, then %s won't be %s anywhere")
					%(colocation["to"], colocation["to_role"], colocation["from"], colocation["from_role"]))
			if colocation["symmetrical"] == "false" :
				desc.append(_("* If %s is %s on the only (or every) available node, %s won't be affected")
						%(colocation["from"], colocation["from_role"], colocation["to"]))
				desc.append("")
			else :
				desc.append(_("* Prevent %s from being %s on the same node as %s %s  ( %s according to %s )")
						%(colocation["to"], colocation["to_role"], colocation["from"], colocation["from_role"],
						colocation["to"], colocation["from"]))
				desc.append(_("* If %s is %s on the only (or every) available node, then %s won't be %s anywhere")
						%(colocation["from"], colocation["from_role"], colocation["to"], colocation["to_role"]))
		else :
			desc.append(_("* Combine this colocation score and the appropriate location scores to decide where to put the resources"))
			desc.append("")
			desc.append("")
			desc.append("")

		return desc

	def dynamic_desc_rng(self, widget) :
		attr_list = self.attr_list
		colocation = self.get_values()
		for attr_name in self.attr_list :
			if attr_name in ["rsc", "with-rsc"] and not colocation.has_key(attr_name) :
				return [_("* Specify where resources should run relative to other resources"),
					_("* Please set the required attributes or add resource sets"), ""]
			if colocation.get(attr_name) == None :
				colocation[attr_name] = ""
		desc = []

		score = self.get_score(colocation["score"])

		comb_tip = _("* Combine this \"Score\" and corresponding location scores to decide where to place %s") \
				%colocation["rsc"]

		if score > 0 :
			if colocation["score"] in ["INFINITY", "infinity", "+INFINITY", "+infinity"] :
				desc.append(_("* Make %s %s on the same node as %s %s  ( %s according to %s )")
						%(colocation["rsc"], colocation["rsc-role"], colocation["with-rsc"], colocation["with-rsc-role"],
						colocation["rsc"], colocation["with-rsc"]))
				desc.append(_("* If %s cannot be %s on any node, then %s won't be %s anywhere")
						%(colocation["with-rsc"], colocation["with-rsc-role"], colocation["rsc"], colocation["rsc-role"]))
				desc.append(_("* If %s cannot be %s on any node, %s won't be affected")
						%(colocation["rsc"], colocation["rsc-role"], colocation["with-rsc"]))
			else :
				desc.append(_("* Prefer to make %s %s on the same node as %s %s  ( %s according to %s )")
					%(colocation["rsc"], colocation["rsc-role"], colocation["with-rsc"], colocation["with-rsc-role"],
					colocation["rsc"], colocation["with-rsc"])) 
				desc.append(comb_tip)
				desc.append("")


		elif score < 0 :
			if colocation["score"] in ["-INFINITY", "-infinity"] :
				desc.append(_("* Prevent %s from being %s on the same node as %s %s  ( %s according to %s )")
						%(colocation["rsc"], colocation["rsc-role"], colocation["with-rsc"], colocation["with-rsc-role"],
						colocation["rsc"], colocation["with-rsc"]))
				desc.append(_("* If %s is %s on the only (or every) available node, then %s won't be %s anywhere")
						%(colocation["with-rsc"], colocation["with-rsc-role"], colocation["rsc"], colocation["rsc-role"]))
				desc.append(_("* If %s is %s on the only (or every) available node, %s won't be affected")
						%(colocation["rsc"], colocation["rsc-role"], colocation["with-rsc"]))
			else :
				desc.append(_("* Prefer to prevent %s from being %s on the same node as %s %s  ( %s according to %s )")
						%(colocation["rsc"], colocation["rsc-role"], colocation["with-rsc"], colocation["with-rsc-role"],
						colocation["rsc"], colocation["with-rsc"])) 
				desc.append(comb_tip)
				desc.append("")
		else :
			desc.append(_("* Please specify a valid \"Score\" to determine the location relationship between %s and %s")
					%(colocation["rsc"], colocation["with-rsc"]))
			desc.append("")
			desc.append("")

		return desc

class TableView :
	all_nodes_widget = []

	def add_rsc(self, rscg, type):
		expanded = chk_expanded(window.maintree, rscg)
		if expanded and type in ["group","clone","master"]:
			for rsc in manager.get_sub_rsc(rscg):
				self.rscs.append(rsc)
				type = manager.get_rsc_type(rsc)
				self.add_rsc(rsc, type)
			

	def update(self, xml_node = None) :
                nodes = manager.get_all_nodes()
                if nodes != None:
                        nodes.sort()

                self.rscs = list()
                rscgs = []
                group_nodes = manager.xml_nodes["cib"].getElementsByTagName("resources")[0]
                for child in group_nodes.childNodes :
                                if child.nodeType != child.ELEMENT_NODE :
                                        continue
                                rscgs.append(str(child.getAttribute('id')))
		try:
			expanded = chk_expanded(window.maintree, _("Resources"))
		except:
			expanded = 0
		drbd_rsc_name = ""
		if rscgs != None and len(rscgs)!=0 and expanded:
                        for rscg in rscgs:
                                type = manager.get_rsc_type(rscg)
	                        if type in ["master"]:
        	                        drbd_rsc_name = rscg
                                self.rscs.append(rscg)
				self.add_rsc(rscg, type)
                                '''expanded = chk_expanded(window.maintree, rscg)
                                if expanded and type in ["group","clone","master"]:
                                        for rsc in manager.get_sub_rsc(rscg):
                                                self.rscs.append(rsc)'''

                left = 0
                right = 1
                self.table = gtk.Table(len(nodes) + 1, len(self.rscs))
                if not pygtk_newer(2, 12) :
	                self.tooltips=gtk.Tooltips()
                #self.all_nodes_widget = []
                for node in nodes:
                        status = window.judge_node_status(node)
                        if status == -1:
                                continue
                        text = node + ' ' + self.infos_srv[status]

                        #neoshine begin
                        drbd_msg = ["", ""]
                        if drbd_rsc_name != "":
                                drbd_msg = self.drbd_warn(drbd_rsc_name)

                        if not manager.get_status_node_links() :
                                if status < 3 :
                                        status = status + 6
                                elif status == 4 :
                                        status = status + 5

                        widget = self.create_icon_label_box(self.icons_srv[status], text+drbd_msg[0], True)
                        #neoshine end

                        widget.set_size_request(200, 60)
                        self.all_nodes_widget.append(widget)
                        widget.connect('button-press-event', self.button_press_cb, node)
			if pygtk_newer(2, 12):
				widget.set_tooltip_text(text+drbd_msg[1])
			else:
                        	self.tooltips.set_tip(widget,text+drbd_msg[1])

                        self.table.attach(widget, left, right, 0, 2)
                        top = 2
                        bottom = 3
                        for rsc in self.rscs:
                                status = self.judge_rsc_status(rsc, node)
                                widget = self.create_icon_label_box(\
                                        self.icons[status], self.infos[status])
                                widget.set_size_request(200, 35)
				if pygtk_newer(2, 12):
					widget.set_tooltip_text(rsc)
				else:
                                	self.tooltips.set_tip(widget,rsc)
                                self.table.attach(widget, left, right, top, bottom)
                                top += 1
                                bottom += 1
                        left += 1
                        right += 1

                #neoshine begin
                for nw in self.all_nodes_widget:
                        nw.modify_bg(gtk.STATE_NORMAL, nw.get_colormap().alloc_color("#dcdddf"))

		self.on_after_show()

        def add_score(self, score1, score2):
                if score1 in ["-INFINITY", "-infinity"] or score2 in ["-INFINITY", "-infinity"] :
                        return str("-INFINITY")
                if score1 in ["INFINITY","+INFINITY", "infinity", "+infinity"] or score2 in ["INFINITY", "+INFINITY", "infinity", "+infinity"] :
                        return str("INFINITY")
                return str(int(score1)+int(score2))

        def drbd_warn(self, drbd_rsc_name):
                msg = ["", ""]
                fail_node = []
		
		try:
			xml_drbd = manager.xml_nodes["cib"].getElementsByTagName("drbd_split")[0]
			for child in xml_drbd.childNodes:
				if child.nodeType != child.ELEMENT_NODE :
					continue
	                        if child.getAttribute('flag') == "on" or child.getAttribute('flag') == "neterr":
					node = str(child.getAttribute('id'))
					fail_node.append(node)
				elif child.getAttribute('flag') == "syncing":
					return [_("DRBD Syncing"), _("Please wait for a moment!\n")+_("DRBD is doing data synchronization now...\n")]
				elif child.getAttribute('flag') == "fixing":
					return [_("DRBD Fixing"), _("Please wait for a moment!\n")+_("DRBD is being repaired now...\n")]
				elif child.getAttribute('flag') == "off":
					return msg
				elif child.getAttribute('flag') == "invalid_ip":
					return [_("\n")+_("DRBD Configuration Error"), _("\n")+_("DRBD communication nic can not be used for Virtual ip. Solution:\n")+_("Way 1. Change the nic of Virtual IP (Recommend);\n")+_("Way 2. or you can set drbd_allow_virtualIP's value to 'true'(Not Safe).\n")+_("And then make the standby node ")+_(" active.")]
					
		except:
			return msg

                if len(fail_node) == 0:
                        return msg
                else:
			msg[0] = _("\n") + _("DRBD Connect Error")
			msg[1] += _("\n") +_("Please check the disk mirroring heartbeat connections!\n")
                return msg

	def on_after_show(self) :
		return

        def judge_rsc_status(self, rsc, node):
                type = manager.get_rsc_type(rsc)
                if type in ["group","clone","master"]:
                        if manager.get_sub_rsc(rsc) != []:
                                for subrsc in manager.get_sub_rsc(rsc):
                                        if self.judge_rsc_status(subrsc, node) != 0:
                                                return 1
                        return 0
                goodnodes = manager.get_rsc_running_on(rsc)
		if goodnodes == None:
			return 1
                for goodnode in goodnodes:
                        if node == goodnode:
                                status = manager.get_rsc_status(rsc)[0]
                                if status == 'not running':
                                        return 1
                                elif status == 'running':
                                        return 0
                                elif status == 'failed':
                                        return 3
                                elif status == 'stop failed':
                                        return 4
                                elif status == 'running (Master)':
                                        return 5
                                elif status == 'running (Slave)':
                                        return 6
                                else:
                                        return 2
                return 1

        def is_sensitive(self, node):
                crm_nodes = manager.get_crm_nodes()
                if node not in crm_nodes:
                        node_type = manager.get_nodetype(node)[0]
                        if node_type == "normal":
                                return False

                if manager.get_node_config(node).get("standby") != "True":
                        return [True, False]
                else:
                        return [False, True]

        def button_press_cb(self, widget, event, node):
                res = self.is_sensitive(node)
                if not res :
                        return

                window.set_action_sensitive('standby', res[0])
                window.set_action_sensitive('active', res[1])
                window.set_action_sensitive('delnode', True)
                window.cur_node_name = node

                #neoshine begin
                if event.type == gtk.gdk.BUTTON_PRESS:
                        for nw in self.all_nodes_widget:
                                nw.modify_bg(gtk.STATE_NORMAL, nw.get_colormap().alloc_color("#dcdddf"))
                        widget.modify_bg(gtk.STATE_NORMAL, widget.get_colormap().alloc_color("#cccccc"))

                        if event.button == 3:
                                menu = window.uimanager.get_widget("/node_popup")
                                menu.popup(None, None, None, event.button, event.time)
                #neoshine end

        def create_icon_label_box(self, icon, text, isnode=False):
                image = gtk.Image()
                if isnode == True:
                        image.set_from_file(icon)
                elif isnode == False:
                        image.set_from_stock(icon, gtk.ICON_SIZE_BUTTON)
                image.show()

                label = gtk.Label()
                label.set_text(text)
                label.show()

                roff = 0.8
                loff = 0.0
                if isnode == True:
                        roff = 1
                aligned_image = gtk.Alignment(roff, 0.5, 0, 0)
                aligned_image.show()
                aligned_image.add(image)
                aligned_label = gtk.Alignment(loff, 0.5, 0, 0)
                aligned_label.show()
                aligned_label.add(label)

                box = gtk.HBox(True, 0)
                box.pack_start(aligned_image, True, True, 0)
                box.pack_start(aligned_label, True, True, 0)

                frame = gtk.Frame()
                frame.set_shadow_type(gtk.SHADOW_ETCHED_IN)
                frame.add(box)

                if isnode == False:
                        eb =gtk.EventBox()
                        eb.add(frame)
                        return eb

                eb = gtk.EventBox()
                eb.set_events(gtk.gdk.BUTTON_PRESS_MASK)
                eb.add(frame)

                return eb


	def __init__(self) :
                self.icons = {
                        0:gtk.STOCK_YES,
                        1:gtk.STOCK_DIALOG_INFO,
                        2:gtk.STOCK_DIALOG_WARNING,
                        3:gtk.STOCK_DIALOG_ERROR,
                        4:gtk.STOCK_DIALOG_ERROR,
                        5:gtk.STOCK_YES,
                        6:gtk.STOCK_YES}

                self.infos = {
                        0:_('Running'),
                        1:_('Not Running'),
                        2:_('Umanaged'),
                        3:_('Failed'),
                        4:_('Stop Failed'),
                        5:_('running (Master)'),
                        6:_('running (Slave)')}

                self.icons_srv = {
                        0:'@HA_DATADIR@/heartbeat-gui/M.png',
                        1:'@HA_DATADIR@/heartbeat-gui/R.png',
                        2:'@HA_DATADIR@/heartbeat-gui/S.png',
                        3:'@HA_DATADIR@/heartbeat-gui/N.png',
                        4:'@HA_DATADIR@/heartbeat-gui/MS.png',
                        5:'@HA_DATADIR@/heartbeat-gui/NS.png',
                        6:'@HA_DATADIR@/heartbeat-gui/M1.gif',
                        7:'@HA_DATADIR@/heartbeat-gui/R1.gif',
                        8:'@HA_DATADIR@/heartbeat-gui/S1.gif',
                        9:'@HA_DATADIR@/heartbeat-gui/MS1.gif'
                        }
                self.infos_srv = {
                        0:_('(Master)'),
                        1:_('(Running)'),
                        2:_('(Standby)'),
                        3:_('(Not Running)'),
                        4:_('(Master/Standby)'),
                        5:_('(Not Running/Standby)')}

		self.update()
                box = gtk.VBox(False, 0)
                box.pack_start(self.table, False, False, 0)
                box.show_all()
		self.widget = box

	def save_status(self) :
		page_num = self.notebook.get_current_page()
		if page_num < 0 :
			return None
		else :
			return (page_num,)

	def restore_status(self, view_status) :
		if view_status == None :
			return
		(page_num,) = view_status
		self.notebook.set_current_page(page_num)

#neoshineha end ming.liu

def log(string) :
	syslog.syslog(string)
	if debug_level > 0 :
		print string
		
def debug(string) :
	if debug_level == 0 :
		return
	syslog.syslog(string)
	print string
	
# If the built-in uuid module is available, don't use the external command uuidgen
try :
	import uuid
	def gen_uuid() :
		return str(uuid.uuid4())
except ImportError :
	def gen_uuid() :
		return os.popen("uuidgen").readline()[:-1]

def cond(condition, vtrue, vfalse) :
	if condition :
		return vtrue
	return vfalse
	
def edited_cb(cell, path, new_text, user_data):
      liststore, column, call_back = user_data
      liststore[path][column] = new_text
      if call_back != None :
	      call_back(None)
      return

def pygtk_newer(major, minor) :
	if gtk.pygtk_version[0] > major :
		return True
	if gtk.pygtk_version[0] == major and gtk.pygtk_version[1] >= minor :
		return True
	return False

def pygobject_newer(major, minor, rel) :
	if gobject.pygobject_version[0] > major :
		return True
	if gobject.pygobject_version[0] == major :
		if gobject.pygobject_version[1] > minor :
			return True
		if gobject.pygobject_version[1] == minor and gobject.pygobject_version[2] >= rel :
			return True
	return False
		
def delete_dir(dir_path) :
	real_path = os.path.realpath(dir_path)
	if real_path.count(os.sep) == len(real_path) :
		msgbox(top_window, _("Do not delete the root directory"))
		return

	for root, dirs, files in os.walk(dir_path, False) :
    		for name in files :
			try :
				os.unlink(os.path.join(root, name))
			except OSError, msg :
				msgbox(top_window, _("System error") + _(": ") + str(msg))
				continue
		for name in dirs :
			try :
				os.rmdir(os.path.join(root, name))
			except OSError, msg :
				msgbox(top_window, _("System error") + _(": ") + str(msg))
				continue
	try :
		os.rmdir(dir_path)
	except OSError, msg :
		msgbox(top_window, _("System error") + _(": ") + str(msg))

def add_column(widget, label, value, icon_cell_func = None, editable = False
		, options=None, call_back=None, visible = True, is_enum = False) :
	tvcolumn = gtk.TreeViewColumn(label)
	widget.append_column(tvcolumn)
	if options == None or options == [] or not pygtk_newer(2, 6):
		cell = gtk.CellRendererText()
	else :
		cell = gtk.CellRendererCombo()
		store = gtk.ListStore(str)
		cell.set_property("model",store)
		for option in options :
			store.append([option])
		cell.set_property("text-column",0)
		if is_enum :
			cell.set_property('has-entry', False)
	
	if editable :
		cell.set_property('editable', True)
		cell.connect('edited', edited_cb, (widget.get_model(), value, call_back))

	if icon_cell_func != None :
		icon_cell = gtk.CellRendererPixbuf()
		tvcolumn.pack_start(icon_cell, False)
	        tvcolumn.set_cell_data_func(icon_cell, icon_cell_func)
	tvcolumn.set_resizable(True)        
	tvcolumn.pack_start(cell, True)
	tvcolumn.add_attribute(cell, 'text', value)
	tvcolumn.set_visible(visible)
	
def on_label_active(event, widget, url) :
	if not url[0] == '/' and not url.startswith("http") :
		url = "http://"+url
	webbrowser.open(url)

def make_label_active(label, text, url) :
	label.set_markup('<span foreground="blue"><u>'+text+'</u></span>')
	label.get_parent().connect("button_press_event", on_label_active, url)
	#label.get_parent().window.set_cursor(gtk.gdk.Cursor(gtk.gdk.HAND1))

def is_valid_time(time_input) :
	num_chars = "0123456789."
	valid_units = ["", "ms", "msec", "us", "usec", "s", "sec", "m", "min", "h", "hr"]
	time_str = time_input.strip()
	if time_str[0] not in num_chars :
		return (False, _("The specified time should be numeric prefixed."))

	unit_str = ""
	for i in range(len(time_str)) :
		if time_str[i] not in num_chars :
			unit_str = time_str[i:].strip()
			break

	unit_list = valid_units[:]
	unit_list.remove("")
	if unit_str not in valid_units :
		return (False, _("The specified time should default with second unit, ") +
				_("or should be suffixed with one of the following units:\n %s")%(", ".join(unit_list)))
	return (True, None)

def is_valid_id(id) :
	if id == None:
		return False
	id_regex = "^[A-Za-z_][\w.-]*$"
	return re.match(id_regex, id)

def extract_int(int_str) :
	for i in range(len(int_str)) :
		if int_str[i].isdigit() :
			num_start = i
			break
	else :
		return None

	for i in range(num_start, len(int_str)) :
		if not int_str[i].isdigit() :
			return int_str[num_start:i]
	else :
			return int_str[num_start:]

def kvbox(title, description, fields, auto_fill = None) :
	global top_window
	dialog = gtk.Dialog(title, top_window, gtk.DIALOG_MODAL,
		(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))
	dialog.set_border_width(5)
	ok_btn = dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
	ok_btn.grab_default()
	ok_btn.grab_focus()

	if description != None :
		label = gtk.Label()
		#label.set_markup('<span size="medium" weight="bold">' + action_des + '</span>')
		label.set_markup('<b>' + description + '</b>')
		label.set_alignment(0, 0)
		#label.show()

		dialog.vbox.pack_start(label, False, padding = 2)

		separator = gtk.HSeparator()
		#separator.show()
		dialog.vbox.pack_start(separator, False, padding = 2)

	table = gtk.Table(2, 1, False)
	widgets = []
	combos = {}
	for row in range(len(fields)):
		if fields[row].auto_gen :
			widgets.append(None)
			continue
		label = gtk.Label(fields[row].label+":")
		label.set_alignment(0, 0.5)
		table.attach(label, 0, 1, row, row+1, xoptions=gtk.FILL, yoptions=gtk.FILL, xpadding=5, ypadding=2)
		if fields[row].options != None and fields[row].options!=[]:
			if fields[row].entry_editable :
				combo = gtk.combo_box_entry_new_text()
			else :
				combo = gtk.combo_box_new_text()
			for option in fields[row].options:
				combo.append_text(option)
			if fields[row].default != None :
				if fields[row].entry_editable :
					combo.child.set_text(fields[row].default)
					combo.child.set_activates_default(True)
				
				else :
					model = combo.get_model()
					iter = model.get_iter_first()
					while iter != None :
						if model.get_value(iter,0) == fields[row].default :
							combo.set_active_iter(iter)
							break
						iter = model.iter_next(iter)
			else :
				if fields[row].entry_editable :
					combo.child.set_text(fields[row].options[0])
					combo.child.set_activates_default(True)
				else :
					combo.set_active(0)
			widgets.append(combo)
			table.attach(combo, 1,2, row, row+1, yoptions=gtk.FILL, xpadding=5, ypadding=2)
			combos[fields[row].key] = combo
		else :
			entry = gtk.Entry()
			if fields[row].default != None :
				entry.set_text(fields[row].default)
			entry.set_activates_default(True)
			widgets.append(entry)
			table.attach(entry, 1,2, row, row+1, xpadding=5, ypadding=2)

	if auto_fill != None :
		if title == _("Add Parameter") and combos.has_key("name"):
			combos["name"].connect("changed", auto_fill, widgets)
		elif title == _("Add Operation") :
			if combos.has_key("name"):
				combos["name"].connect("changed", auto_fill, widgets, "name")
			if combos.has_key("role"):
				combos["role"].connect("changed", auto_fill, widgets, "role")
	
	dialog.vbox.pack_start(table, padding=2)
	dialog.vbox.show_all()
	save_top_window = top_window
	top_window = dialog

	while True :
		ret = dialog.run()
		if ret in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT] :
			top_window = save_top_window
			dialog.destroy()
			return None
		else :
			kv = {}
			passed = True
			for row in range(len(fields)):
				if fields[row].auto_gen :
					kv[fields[row].key] = gen_uuid()
					continue
				if fields[row].options != None and fields[row].options != []:
					combo = widgets[row]
					if fields[row].entry_editable :
						kv[fields[row].key] = combo.child.get_text()
					else :
						if pygtk_newer(2, 6) :
							kv[fields[row].key] = combo.get_active_text()
						else :
							iter = combo.get_active_iter()
							if iter != None :
								kv[fields[row].key] = combo.get_model().get_value(iter, 0)
							else :
								kv[fields[row].key] = ""
				else :
					entry = widgets[row]
					kv[fields[row].key] = entry.get_text()
				if not fields[row].can_be_empty and kv[fields[row].key] == "" :
					msgbox(top_window, fields[row].label+_(" can't be empty"))
					passed = False
			if passed :
				top_window = save_top_window
				dialog.destroy()
				return kv

if __name__ == '__main__' :
	try :
		gtk._gtk.init_check()
	except RuntimeError :
		print "Could not open display"
		sys.exit()
	except AttributeError :
		pass
	if not pygtk_newer(2, 4) :
		print "the pygtk 2.4 or newer is needed."
		sys.exit()
	gc.enable()
	syslog.openlog("haclient", 0, syslog.LOG_USER)
	locale.setlocale(locale.LC_ALL, '')
	gettext.bindtextdomain(app_name)
	gettext.textdomain(app_name)
	gettext.install(app_name,"@HA_DATADIR@/locale",unicode=1)
	if "-v" in sys.argv :
		debug_level = 1
	manager = Manager()
	window = MainWindow()
	top_window = window.win_widget
	manager.run()
	syslog.closelog()
